Exemple #1
0
VOID
FatForceCacheMiss (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN FAT_FLUSH_TYPE FlushType
    )

/*++

Routine Description:

    The following routine asks either Cc or Mm to get rid of any cached
    pages on a file.  Note that this will fail if a user has mapped a file.

    If there is a shared cache map, purge the cache section.  Otherwise
    we have to go and ask Mm to blow away the section.

    NOTE: This caller MUST own the Vcb exclusive.

Arguments:

    Fcb - Supplies a pointer to an fcb

    FlushType - Specifies the kind of flushing to perform
    
Return Value:

    None.

--*/

{
    PVCB Vcb;
    BOOLEAN ChildrenAcquired = FALSE;

    PAGED_CODE();

    //
    //  If we can't wait, bail.
    //

    ASSERT( FatVcbAcquiredExclusive( IrpContext, Fcb->Vcb ) ||
            FlagOn( Fcb->Vcb->VcbState, VCB_STATE_FLAG_LOCKED ) );

    if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

        FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    }

    //
    //  If we are purging a directory file object, we must acquire all the
    //  FCBs exclusive so that the parent directory is not being pinned.
    //  Careful, we can collide with something acquiring up the tree like
    //  an unpin repinned flush (FsRtlAcquireFileForCcFlush ...) of a parent
    //  dir on extending writethrough of a child file (oops).  So get things
    //  going up the tree, not down.
    //

    if ((NodeType(Fcb) != FAT_NTC_FCB) &&
        !IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue)) {

        PLIST_ENTRY Links;
        PFCB TempFcb;

        ChildrenAcquired = TRUE;

        for (Links = Fcb->Specific.Dcb.ParentDcbQueue.Flink;
             Links != &Fcb->Specific.Dcb.ParentDcbQueue;
             Links = Links->Flink) {

            TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );

            (VOID)FatAcquireExclusiveFcb( IrpContext, TempFcb );
        }
    }

    (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );

    //
    //  We use this flag to indicate to a close beneath us that
    //  the Fcb resource should be freed before deleting the Fcb.
    //

    Vcb = Fcb->Vcb;

    SetFlag( Fcb->FcbState, FCB_STATE_FORCE_MISS_IN_PROGRESS );

    ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );

    try {

        BOOLEAN DataSectionExists;
        BOOLEAN ImageSectionExists;

        PSECTION_OBJECT_POINTERS Section;

        if ( FlushType ) {

            (VOID)FatFlushFile( IrpContext, Fcb, FlushType );
        }

        //
        //  The Flush may have made the Fcb go away
        //

        if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB)) {

            Section = &Fcb->NonPaged->SectionObjectPointers;

            DataSectionExists = (BOOLEAN)(Section->DataSectionObject != NULL);
            ImageSectionExists = (BOOLEAN)(Section->ImageSectionObject != NULL);

            //
            //  Note, it is critical to do the Image section first as the
            //  purge of the data section may cause the image section to go
            //  away, but the opposite is not true.
            //

            if (ImageSectionExists) {

                (VOID)MmFlushImageSection( Section, MmFlushForWrite );
            }

            if (DataSectionExists) {

                CcPurgeCacheSection( Section, NULL, 0, FALSE );
            }
        }

    } finally {

        //
        //  If we purging a directory file object, release all the Fcb
        //  resources that we acquired above.  The Dcb cannot have vanished
        //  if there were Fcbs underneath it, and the Fcbs couldn't have gone
        //  away since I own the Vcb.
        //

        if (ChildrenAcquired) {

            PLIST_ENTRY Links;
            PFCB TempFcb;

            for (Links = Fcb->Specific.Dcb.ParentDcbQueue.Flink;
                 Links != &Fcb->Specific.Dcb.ParentDcbQueue;
                 Links = Links->Flink) {

                TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );

                FatReleaseFcb( IrpContext, TempFcb );
            }
        }

        //
        //  Since we have the Vcb exclusive we know that if any closes
        //  come in it is because the CcPurgeCacheSection caused the
        //  Fcb to go away.  Also in close, the Fcb was released
        //  before being freed.
        //

        if ( !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB) ) {

            ClearFlag( Fcb->FcbState, FCB_STATE_FORCE_MISS_IN_PROGRESS );

            FatReleaseFcb( (IRPCONTEXT), Fcb );
        }
    }
}
Exemple #2
0
long PlugInShell_SetPluginState(const unsigned long inNewState)
{
    long macError = eDSNoErr;
    bool isAcquired = false;

    LOG_ENTER("inNewState = 0x%08x (%s)", inNewState, StateToString(inNewState));

    GS_VERIFY_INITIALIZED(macError);

    if (FlagOn(inNewState, ~(kActive | kInactive)))
    {
        LOG("Ignoring unexpected state flags: 0x%08x", FlagOn(inNewState, ~(kActive | kInactive)));
    }

    if (!FlagOn(inNewState, kActive | kInactive))
    {
        // Nothing to do.
        LOG("Nothing to do because inactive/active flags are not specified.");
        macError = eDSNoErr;
        GOTO_CLEANUP();
    }

    if (FlagOn(inNewState, kActive) && FlagOn(inNewState, kInactive))
    {
        LOG_ERROR("Cannot set active and inactive at the same time.");
        macError = ePlugInError;
        GOTO_CLEANUP();
    }

    GS_ACQUIRE_EXCLUSIVE();
    isAcquired = true;

    LOG("Current State = 0x%08x", GlobalState.PluginState);

    if ( (FlagOn(inNewState, kActive | kInactive) == FlagOn(GlobalState.PluginState, kActive | kInactive)) )
    {
        // Nothing to do.
        LOG("Nothing to do because the state matches");
        macError = eDSNoErr;
        GOTO_CLEANUP();
    }

    if ( FlagOn(inNewState, kActive) )
    {
        LOG("Activating");
        macError = Activate();
        GOTO_CLEANUP_ON_MACERROR(macError);

        SetFlag(GlobalState.PluginState, kActive);
        ClearFlag(GlobalState.PluginState, kInactive);
    }
    else if ( FlagOn(inNewState, kInactive) )
    {
        LOG("De-activating");
        macError = Deactivate();
        GOTO_CLEANUP_ON_MACERROR(macError);

        ClearFlag(GlobalState.PluginState, kActive);
        SetFlag(GlobalState.PluginState, kInactive);
    }
    else
    {
        // This should never happen.
        LOG_ERROR("Benign unexpected code path.");
        macError = eDSNoErr;
    }

cleanup:

    if (isAcquired)
    {
        LOG("Final State = 0x%08x", GlobalState.PluginState);
        GS_RELEASE();
    }

    LOG_LEAVE("--> %d", macError);
    return macError;
}
Exemple #3
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;
}
Exemple #4
0
NTSTATUS
RtlAdjustTokenPrivileges(
    IN PACCESS_TOKEN AccessToken,
    IN BOOLEAN DisableAll,
    IN OPTIONAL PTOKEN_PRIVILEGES NewState,
    IN ULONG BufferLength,
    OUT OPTIONAL PTOKEN_PRIVILEGES PreviousState,
    OUT OPTIONAL PULONG pReturnedLength
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN isLocked = FALSE;
    PLUID_AND_ATTRIBUTES pPrivileges = AccessToken->Privileges;
    ULONG assignedIndex = 0;
    ULONG modIndex = 0;
    ULONG returnedIndex = 0;
    ULONG BufferUsed = 0;
    ULONG adjustedCount = 0;

    if (!DisableAll && !NewState)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!NewState && BufferLength > 0)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    EXCLUSIVE_LOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (AccessToken->PrivilegeCount == 0)
    {
        status = STATUS_NOT_ALL_ASSIGNED;
        GOTO_CLEANUP();
    }

    if (DisableAll)
    {
        for (assignedIndex = 0;
             assignedIndex < AccessToken->PrivilegeCount;
             assignedIndex++)
        {
            status = RtlpAppendTokenPrivileges(
                                PreviousState,
                                BufferLength,
                                &pPrivileges[assignedIndex],
                                returnedIndex++,
                                &BufferUsed);
            if (status == STATUS_SUCCESS)
            {
                ClearFlag(pPrivileges[assignedIndex].Attributes,
                          SE_PRIVILEGE_ENABLED);
            }
        }

        GOTO_CLEANUP();
    }

    for (modIndex = 0;
         modIndex < NewState->PrivilegeCount;
         modIndex++)
    {
        for (assignedIndex = 0;
             assignedIndex < AccessToken->PrivilegeCount;
             assignedIndex++)
        {
            if (RtlEqualLuid(&NewState->Privileges[modIndex].Luid,
                             &pPrivileges[assignedIndex].Luid))
            {
                if (NewState->Privileges[modIndex].Attributes == 0)
                {
                    status = RtlpAppendTokenPrivileges(
                                        PreviousState,
                                        BufferLength,
                                        &pPrivileges[assignedIndex],
                                        returnedIndex++,
                                        &BufferUsed);
                    if (status == STATUS_SUCCESS)
                    {
                        ClearFlag(pPrivileges[assignedIndex].Attributes,
                                  SE_PRIVILEGE_ENABLED);
                        adjustedCount++;
                    }
                }

                if (IsSetFlag(NewState->Privileges[modIndex].Attributes,
                              SE_PRIVILEGE_ENABLED))
                {
                    status = RtlpAppendTokenPrivileges(
                                        PreviousState,
                                        BufferLength,
                                        &pPrivileges[assignedIndex],
                                        returnedIndex++,
                                        &BufferUsed);
                    if (status == STATUS_SUCCESS)
                    {
                        SetFlag(pPrivileges[assignedIndex].Attributes,
                                SE_PRIVILEGE_ENABLED);
                        adjustedCount++;
                    }
                }

                if (IsSetFlag(NewState->Privileges[modIndex].Attributes,
                              SE_PRIVILEGE_REMOVED))
                {
                    if (assignedIndex + 1 < AccessToken->PrivilegeCount)
                    {
                        RtlMoveMemory(
                              &pPrivileges[assignedIndex],
                              &pPrivileges[assignedIndex + 1],
                              sizeof(pPrivileges[0]) * 
                              AccessToken->PrivilegeCount - assignedIndex - 1);
                    }

                    RtlZeroMemory(
                          &pPrivileges[AccessToken->PrivilegeCount - 1],
                          sizeof(pPrivileges[0]));

                    AccessToken->PrivilegeCount--;
                    adjustedCount++;
                }

                break;
            }
        }
    }

cleanup:
    if (PreviousState && (BufferUsed > BufferLength))
    {
        // There was not enough space in PreviousState buffer so roll 
        // the changes back and return STATUS_BUFFER_TOO_SMALL
        for (returnedIndex = 0;
             returnedIndex < PreviousState->PrivilegeCount;
             returnedIndex++)
        {
            for (assignedIndex = 0;
                 assignedIndex < AccessToken->PrivilegeCount;
                 assignedIndex++)
            {
                if (RtlEqualLuid(&PreviousState->Privileges[returnedIndex].Luid,
                                 &pPrivileges[assignedIndex].Luid))
                {
                    pPrivileges[assignedIndex].Attributes
                        = PreviousState->Privileges[returnedIndex].Attributes;
                }
            }
        }

        status = STATUS_BUFFER_TOO_SMALL;
    }

    UNLOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (status == STATUS_SUCCESS &&
        !DisableAll &&
        adjustedCount < NewState->PrivilegeCount)
    {
        status = STATUS_NOT_ALL_ASSIGNED;
    }

    if (pReturnedLength &&
        (status == STATUS_SUCCESS ||
         status == STATUS_BUFFER_TOO_SMALL ||
         status == STATUS_NOT_ALL_ASSIGNED))
    {
        *pReturnedLength = BufferUsed;
    }
    else
    {
        *pReturnedLength = 0;
    }

    return status;
}
nsresult nsMailboxProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
{
  nsresult rv = NS_OK;
  // if we were already initialized with a consumer, use it...
  nsCOMPtr<nsIStreamListener> consumer = do_QueryInterface(aConsumer);
  if (consumer)
    m_channelListener = consumer;
  
  if (aURL)
  {
    m_runningUrl = do_QueryInterface(aURL);
    if (m_runningUrl)
    {
      // find out from the url what action we are supposed to perform...
      rv = m_runningUrl->GetMailboxAction(&m_mailboxAction);
      
      PRBool convertData = PR_FALSE;

      // need to check if we're fetching an rfc822 part in order to
      // quote a message.
      if (m_mailboxAction == nsIMailboxUrl::ActionFetchMessage)
      {
        nsCOMPtr<nsIMsgMailNewsUrl> msgUrl = do_QueryInterface(m_runningUrl, &rv);
        NS_ENSURE_SUCCESS(rv,rv);

        nsCAutoString queryStr;
        rv = msgUrl->GetQuery(queryStr);
        NS_ENSURE_SUCCESS(rv,rv);

        // check if this is a filter plugin requesting the message.
        // in that case, set up a text converter
        convertData = (queryStr.Find("header=filter") != kNotFound || queryStr.Find("header=attach") != kNotFound);
      }
      else if (m_mailboxAction == nsIMailboxUrl::ActionFetchPart)
      {
        // when fetching a part, we need to insert a converter into the listener chain order to
        // force just the part out of the message. Our channel listener is the consumer we'll
        // pass in to AsyncConvertData.
        convertData = PR_TRUE;
        consumer = m_channelListener;
      }
      if (convertData)
      {
          nsCOMPtr<nsIStreamConverterService> streamConverter = do_GetService("@mozilla.org/streamConverters;1", &rv);
          NS_ENSURE_SUCCESS(rv, rv);
          nsCOMPtr <nsIStreamListener> conversionListener;
          nsCOMPtr<nsIChannel> channel;
          QueryInterface(NS_GET_IID(nsIChannel), getter_AddRefs(channel));

          rv = streamConverter->AsyncConvertData("message/rfc822",
                                                 "*/*",
                                                 consumer, channel, getter_AddRefs(m_channelListener));
      }
      
      if (NS_SUCCEEDED(rv))
      {
        switch (m_mailboxAction)
        {
        case nsIMailboxUrl::ActionParseMailbox:
          // extract the mailbox parser..
          rv = m_runningUrl->GetMailboxParser(getter_AddRefs(m_mailboxParser));
          m_nextState = MAILBOX_READ_FOLDER;
          break;
        case nsIMailboxUrl::ActionSaveMessageToDisk:
          // ohhh, display message already writes a msg to disk (as part of a hack)
          // so we can piggy back off of that!! We just need to change m_tempMessageFile
          // to be the name of our save message to disk file. Since save message to disk
          // urls are run without a docshell to display the msg into, we won't be trying
          // to display the message after we write it to disk...
          {
            nsCOMPtr<nsIMsgMessageUrl> msgUri = do_QueryInterface(m_runningUrl);
            msgUri->GetMessageFile(getter_AddRefs(m_tempMessageFile));
            NS_NewLocalFileOutputStream(getter_AddRefs(m_msgFileOutputStream), m_tempMessageFile, -1, 00600);
          }
        case nsIMailboxUrl::ActionCopyMessage:
        case nsIMailboxUrl::ActionMoveMessage:
        case nsIMailboxUrl::ActionFetchMessage:
          if (m_mailboxAction == nsIMailboxUrl::ActionSaveMessageToDisk) 
          {
            nsCOMPtr<nsIMsgMessageUrl> messageUrl = do_QueryInterface(aURL, &rv);
            if (NS_SUCCEEDED(rv))
            {
              PRBool addDummyEnvelope = PR_FALSE;
              messageUrl->GetAddDummyEnvelope(&addDummyEnvelope);
              if (addDummyEnvelope)
                SetFlag(MAILBOX_MSG_PARSE_FIRST_LINE);
              else
                ClearFlag(MAILBOX_MSG_PARSE_FIRST_LINE);
            }
          }
          else
          {
            ClearFlag(MAILBOX_MSG_PARSE_FIRST_LINE);
          }
          
          m_nextState = MAILBOX_READ_MESSAGE;
          break;
        case nsIMailboxUrl::ActionFetchPart:
            m_nextState = MAILBOX_READ_MESSAGE;
            break;
        default:
          break;
        }
      }
      
      rv = nsMsgProtocol::LoadUrl(aURL, m_channelListener);
      
    } // if we received an MAILBOX url...
  } // if we received a url!
  
  return rv;
}
Exemple #6
0
VOID
CdFspClose (
    _In_opt_ PVCB Vcb
    )

/*++

Routine Description:

    This routine is called to process the close queues in the CdData.  If the
    Vcb is passed then we want to remove all of the closes for this Vcb.
    Otherwise we will do as many of the delayed closes as we need to do.

Arguments:

    Vcb - If specified then we are looking for all of the closes for the
        given Vcb.

Return Value:

    None

--*/

{
    PIRP_CONTEXT IrpContext;
    IRP_CONTEXT StackIrpContext;

    THREAD_CONTEXT ThreadContext = {0};

    PFCB Fcb;
    ULONG UserReference;

    ULONG VcbHoldCount = 0;
    PVCB CurrentVcb = NULL;

    BOOLEAN PotentialVcbTeardown = FALSE;

    PAGED_CODE();

    FsRtlEnterFileSystem();

    //
    //  Continue processing until there are no more closes to process.
    //

    while ((IrpContext = CdRemoveClose( Vcb )) != NULL) {

        //
        //  If we don't have an IrpContext then use the one on the stack.
        //  Initialize it for this request.
        //

        if (SafeNodeType( IrpContext ) != CDFS_NTC_IRP_CONTEXT ) {

            //
            //  Update the local values from the IrpContextLite.
            //

            Fcb = ((PIRP_CONTEXT_LITE) IrpContext)->Fcb;
            UserReference = ((PIRP_CONTEXT_LITE) IrpContext)->UserReference;

            //
            //  Update the stack irp context with the values from the
            //  IrpContextLite.
            //

            CdInitializeStackIrpContext( &StackIrpContext,
                                         (PIRP_CONTEXT_LITE) IrpContext );

            //
            //  Free the IrpContextLite.
            //

            CdFreeIrpContextLite( *(PVOID*)&IrpContext ); /* ReactOS Change: GCC "error: invalid lvalue in unary '&'" */

            //
            //  Remember we have the IrpContext from the stack.
            //

            IrpContext = &StackIrpContext;

        //
        //  Otherwise cleanup the existing IrpContext.
        //

        } else {

            //
            //  Remember the Fcb and user reference count.
            //

            Fcb = (PFCB) IrpContext->Irp;
            IrpContext->Irp = NULL;

            UserReference = (ULONG) IrpContext->ExceptionStatus;
            IrpContext->ExceptionStatus = STATUS_SUCCESS;
        }

        _Analysis_assume_(Fcb != NULL && Fcb->Vcb != NULL);

        //
        //  We have an IrpContext.  Now we need to set the top level thread
        //  context.
        //

        SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS );

        //
        //  If we were given a Vcb then there is a request on top of this.
        //

        if (ARGUMENT_PRESENT( Vcb )) {

            ClearFlag( IrpContext->Flags,
                       IRP_CONTEXT_FLAG_TOP_LEVEL | IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS );
        }

        CdSetThreadContext( IrpContext, &ThreadContext );

        //
        //  If we have hit the maximum number of requests to process without
        //  releasing the Vcb then release the Vcb now.  If we are holding
        //  a different Vcb to this one then release the previous Vcb.
        //
        //  In either case acquire the current Vcb.
        //
        //  We use the MinDelayedCloseCount from the CdData since it is
        //  a convenient value based on the system size.  Only thing we are trying
        //  to do here is prevent this routine starving other threads which
        //  may need this Vcb exclusively.
        //
        //  Note that the check for potential teardown below is unsafe.  We'll 
        //  repeat later within the cddata lock.
        //

        PotentialVcbTeardown = !ARGUMENT_PRESENT( Vcb ) &&
                               (Fcb->Vcb->VcbCondition != VcbMounted) &&
                               (Fcb->Vcb->VcbCondition != VcbMountInProgress) &&
                               (Fcb->Vcb->VcbCleanup == 0);

        if (PotentialVcbTeardown ||
            (VcbHoldCount > CdData.MinDelayedCloseCount) ||
            (Fcb->Vcb != CurrentVcb)) {

            if (CurrentVcb != NULL) {

                CdReleaseVcb( IrpContext, CurrentVcb );
            }

            if (PotentialVcbTeardown) {

                CdAcquireCdData( IrpContext );

                //
                //  Repeat the checks with global lock held.  The volume could have
                //  been remounted while we didn't hold the lock.
                //

                PotentialVcbTeardown = !ARGUMENT_PRESENT( Vcb ) &&
                                       (Fcb->Vcb->VcbCondition != VcbMounted) &&
                                       (Fcb->Vcb->VcbCondition != VcbMountInProgress) &&
                                       (Fcb->Vcb->VcbCleanup == 0);
                                
                if (!PotentialVcbTeardown)  {

                    CdReleaseCdData( IrpContext);
                }
            }

            CurrentVcb = Fcb->Vcb;

            _Analysis_assume_( CurrentVcb != NULL );
            
            CdAcquireVcbShared( IrpContext, CurrentVcb, FALSE );

            VcbHoldCount = 0;

        } else {

            VcbHoldCount += 1;
        }

        //
        //  Call our worker routine to perform the close operation.
        //

        CdCommonClosePrivate( IrpContext, CurrentVcb, Fcb, UserReference, FALSE );

        //
        //  If the reference count on this Vcb is below our residual reference
        //  then check if we should dismount the volume.
        //

        if (PotentialVcbTeardown) {

            CdReleaseVcb( IrpContext, CurrentVcb );
            CdCheckForDismount( IrpContext, CurrentVcb, FALSE );

            CurrentVcb = NULL;

            CdReleaseCdData( IrpContext );
            PotentialVcbTeardown = FALSE;
        }

        //
        //  Complete the current request to cleanup the IrpContext.
        //

        CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
    }

    //
    //  Release any Vcb we may still hold.
    //

    if (CurrentVcb != NULL) {

        CdReleaseVcb( IrpContext, CurrentVcb );

    }

#ifdef _MSC_VER
#pragma prefast(suppress:26165, "Esp:1153")
#endif
    FsRtlExitFileSystem();
}
VOID
PrimarySessionThreadProc (
	IN PPRIMARY_SESSION PrimarySession
	)
{
	BOOLEAN		primarySessionTerminate = FALSE;
	NTSTATUS	status;
	_U16		slotIndex;
	PLIST_ENTRY	primarySessionRequestEntry;


	ASSERT( SESSION_SLOT_COUNT == 1 );
	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	DebugTrace2( 0, Dbg2, ("PrimarySessionThreadProc: Start PrimarySession = %p\n", PrimarySession) );
	
	PrimarySession_Reference( PrimarySession );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	
	InitializeListHead( &PrimarySession->Thread.OpenedFileQueue );
	KeInitializeSpinLock( &PrimarySession->Thread.OpenedFileQSpinLock );

	KeInitializeEvent( &PrimarySession->Thread.WorkCompletionEvent, NotificationEvent, FALSE );

	PrimarySession->SessionContext.SessionSlotCount = SESSION_SLOT_COUNT;

	for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) {

		PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
		PrimarySession->Thread.IdleSlotCount ++;
	}

	ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_START );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );

	KeSetEvent( &PrimarySession->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
										    &PrimarySession->Thread.TdiReceiveContext,
										    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
										    sizeof(NDFS_REQUEST_HEADER),
										    0,
										    NULL,
										    NULL );

	if (NT_SUCCESS(status)) {

		PrimarySession->Thread.TdiReceiving = TRUE;
	
	} else {
	
		ASSERT( NDASFAT_BUG );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
		primarySessionTerminate = TRUE;
	} 

	while (primarySessionTerminate == FALSE) {

		PKEVENT				events[3];
		LONG				eventCount;
		NTSTATUS			eventStatus;
		LARGE_INTEGER		timeOut;


		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;

		events[eventCount++] = &PrimarySession->RequestEvent;

		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			events[eventCount++] = &PrimarySession->Thread.WorkCompletionEvent;

			if (FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN)) {
			
				if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount) {

					CloseOpenFiles( PrimarySession, TRUE );
				
					KeSetEvent( &PrimarySession->Thread.ShutdownPrimarySessionRequest->CompleteEvent, 
								IO_DISK_INCREMENT, 
								FALSE );

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT );
					ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );
				}
			}	 
		
			if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT)) {

				if (PrimarySession->Thread.TdiReceiving == TRUE) {

					ASSERT( PrimarySession->Thread.IdleSlotCount != 0 );
					events[eventCount++] = &PrimarySession->Thread.TdiReceiveContext.CompletionEvent;
				}
			}

			ASSERT( eventCount <= THREAD_WAIT_OBJECTS );
		}

		timeOut.QuadPart = -5*HZ;
		eventStatus = KeWaitForMultipleObjects( eventCount, 
												events, 
												WaitAny, 
												Executive, 
												KernelMode,
												TRUE,
												&timeOut,
												NULL );

#if 0
		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			if (eventStatus == STATUS_TIMEOUT || eventStatus == 2) {
			
				if (PrimarySession->Thread.SessionState == SESSION_TREE_CONNECT) {
				
					ASSERT( PrimarySession->NetdiskPartition );
				
					if (!(PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_PRIMARY].VolumeState == VolumeMounted || 
						  PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_SECONDARY2PRIMARY].VolumeState == VolumeMounted)) {

						DebugTrace2( 0, Dbg2,
									   ("Netdisk Volume is unmounted\n") );

						if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT))
							primarySessionTerminate = TRUE;
		
						continue;
					}
				}
			}
		}

#endif

		if (eventStatus == STATUS_TIMEOUT) {

			continue;
		}

		if (!NT_SUCCESS(eventStatus) || eventStatus >= eventCount) {

			NdasFatDbgBreakPoint();
			SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
			primarySessionTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																			 &PrimarySession->RequestQSpinLock)) {

				PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
				primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
														   PRIMARY_SESSION_REQUEST,
														   ListEntry );

				if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT ||
					primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE) {

					DebugTrace2( 0, Dbg2, 
								   ((primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT) ?
								   ("PRIMARY_SESSION_REQ_DISCONNECT: DisconnectFromSecondary\n") :
									("PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE: DisconnectFromSecondary\n")) );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE)
						primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DOWN) {
					
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
					primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );
				
				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_SHUTDOWN) {

					DebugTrace2( 0, Dbg, ("PrimarySessionThreadProc: PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN\n") );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );

					ASSERT (primarySessionRequest->Synchronous == TRUE);

					PrimarySession->Thread.ShutdownPrimarySessionRequest = primarySessionRequest;

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_STOPPING) {

					SetFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );
					
					if (PrimarySession->IsLocalAddress == FALSE) {

						CloseOpenFiles( PrimarySession, FALSE );
					}

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_CANCEL_STOPPING) {

					ClearFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else {

					ASSERT( NDASFAT_BUG );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
				}
			}

			continue;
		
		} else if (eventStatus == 1) {

			while (TRUE) {
	
				for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) {

					if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
						break;
				}

				if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
					break;
			
				PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
				PrimarySession->Thread.IdleSlotCount ++;

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					PNDFS_REPLY_HEADER		ndfsReplyHeader;

					ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[slotIndex].ReplyMessageBuffer;
										
					PrimarySession->Thread.SessionSlot[slotIndex].Status
						= SendNdfsWinxpMessage( PrimarySession,
												ndfsReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].NdfsWinxpReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].ReplyDataSize,
												slotIndex );

				}
	
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}
		
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}

				if (!(PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS || 
					  PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_PENDING)) {

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );

#if 0
					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );

						PrimarySession->NetdiskPartition = NULL;
					}
#endif

					primarySessionTerminate = TRUE;
					break;		
				 }
				
				if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

#if 0
					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );
	
						PrimarySession->NetdiskPartition = NULL;
					}
#endif

					primarySessionTerminate = TRUE;
					break;		
				}

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					if (PrimarySession->Thread.TdiReceiving == FALSE) {

						status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
															    &PrimarySession->Thread.TdiReceiveContext,
															    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
															    sizeof(NDFS_REQUEST_HEADER),
															    0,
															    NULL,
															    NULL );

						if (!NT_SUCCESS(status)) {

							ASSERT( NDASFAT_BUG );

							SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
							primarySessionTerminate = TRUE;
							break;
						}
						
						PrimarySession->Thread.TdiReceiving = TRUE;
					}
				}
			}		
		
			continue;
		
		} else {

			ASSERT( eventStatus == 2 );  // Receive Event
			ASSERT( !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT) &&
				    !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN) );

			if (PrimarySession->Thread.TdiReceiveContext.Result != sizeof(NDFS_REQUEST_HEADER)) {

				DebugTrace2( 0, Dbg,
							   ("DispatchRequest: Disconnected, PrimarySession = Data received:%d\n",
							   PrimarySession->Thread.TdiReceiveContext.Result) );

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
				primarySessionTerminate = TRUE;
				
				continue;		
			}

			PrimarySession->Thread.TdiReceiving = FALSE;

#if 0
			if (PrimarySession->NetdiskPartition) {

				PENABLED_NETDISK EnabledNetdisk = PrimarySession->NetdiskPartition->EnabledNetdisk;
				
				ASSERT( EnabledNetdisk );

				if (NetdiskManager_IsStoppedNetdisk(GlobalLfs.NetdiskManager, EnabledNetdisk)) {
				    
					DebugTrace2( 0, Dbg2,
								   ("PrimarySessionThread: %p Netdisk is stopped\n", PrimarySession) );

					DebugTrace2( 0, Dbg2, ("DispatchWinXpRequest: Netdisk is stopped.\n") );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) { 
					
						// no other way to notify secondary about unmount without break backward compatability.
						
						DebugTrace2( 0, Dbg2, ("IsStoppedNetdisk: DisconnectFromSecondary\n") );
						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					primarySessionTerminate = TRUE;
					continue;
				}
			} 

#endif

			status = DispatchRequest( PrimarySession );

			if (!(status == STATUS_SUCCESS || status == STATUS_PENDING)) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (status == STATUS_SUCCESS) {

				if (PrimarySession->Thread.TdiReceiving == FALSE) {

					status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
														    &PrimarySession->Thread.TdiReceiveContext,
														    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
														    sizeof(NDFS_REQUEST_HEADER),
														    0,
														    NULL,
														    NULL );

					if (!NT_SUCCESS(status)) {

						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
						primarySessionTerminate = TRUE;
					}

					PrimarySession->Thread.TdiReceiving = TRUE;
				}
			}
			
			continue;
		}
	}

	ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
	ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );

	while (TRUE) {

		LARGE_INTEGER	timeOut;
		NTSTATUS		eventStatus;


		if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount)
			break;

		timeOut.QuadPart = -10*HZ;
		eventStatus = KeWaitForSingleObject( &PrimarySession->Thread.WorkCompletionEvent,
											 Executive,
											 KernelMode,
											 FALSE,
											 &timeOut );

		KeClearEvent( &PrimarySession->Thread.WorkCompletionEvent );

		if (eventStatus == STATUS_TIMEOUT) {

			ASSERT( NDASFAT_UNEXPECTED );
			continue;
		}

		while (TRUE) {
	
			for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex++) {

				if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
					break;
			}

			if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
				break;

			DebugTrace2( 0, Dbg, ("PrimarySessionThreadProc: eventStatus = %d\n", eventStatus) );
			
			PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
			PrimarySession->Thread.IdleSlotCount++;

			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		
			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		}		
	}
	
	if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

		DebugTrace2( 0, Dbg2, ("PsTerminateSystemThread: DisconnectFromSecondary\n") );
		DisconnectFromSecondary( PrimarySession );
		ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
	}

	CloseOpenFiles( PrimarySession, TRUE );

	while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																	 &PrimarySession->RequestQSpinLock)) {

		PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
		primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
												   PRIMARY_SESSION_REQUEST,
												   ListEntry );

		if (primarySessionRequest->Synchronous == TRUE)
			KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferencePrimarySessionRequest( primarySessionRequest );
	}

#if 0
	if (PrimarySession->NetdiskPartition) {

		NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager,
											   PrimarySession,
											   PrimarySession->NetdiskPartition, 
											   PrimarySession->IsLocalAddress );

		PrimarySession->NetdiskPartition = NULL;
	}
#endif

	DebugTrace2( 0, Dbg2,
				   ("PrimarySessionThreadProc: PsTerminateSystemThread PrimarySession = %p\n", 
				    PrimarySession) );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_TERMINATED );

	PrimarySession_Dereference( PrimarySession );

	PsTerminateSystemThread( STATUS_SUCCESS );
}
Exemple #8
0
NTSTATUS
AFSClose( IN PDEVICE_OBJECT LibDeviceObject,
          IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    ULONG ulRequestType = 0;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFcb *pFcb = NULL;
    AFSDeviceExt *pDeviceExt = NULL;
    AFSCcb *pCcb = NULL;
    AFSObjectInfoCB *pObjectInfo = NULL;
    AFSDirectoryCB *pDirCB = NULL;

    __try
    {

        if( AFSRDRDeviceObject == NULL)
        {

            //
            // Let this through, it's an close on the library control device
            //

            try_return( ntStatus);
        }

        pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;

        pIrpSp = IoGetCurrentIrpStackLocation( Irp);

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

        if( pFcb == NULL)
        {
            try_return( ntStatus);
        }

        pObjectInfo = pFcb->ObjectInformation;

        //
        // Perform the close functionality depending on the type of node it is
        //

        switch( pFcb->Header.NodeTypeCode)
        {

            case AFS_IOCTL_FCB:
            {

                AFSPIOCtlOpenCloseRequestCB stPIOCtlClose;
                AFSFileID stParentFileId;

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

                //
                // Send the close to the CM
                //

                RtlZeroMemory( &stPIOCtlClose,
                               sizeof( AFSPIOCtlOpenCloseRequestCB));

                stPIOCtlClose.RequestId = pCcb->RequestID;

                stPIOCtlClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;

                RtlZeroMemory( &stParentFileId,
                               sizeof( AFSFileID));

                stParentFileId = pObjectInfo->ParentObjectInformation->FileId;

                //
                // Issue the close request to the service
                //

                AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_CLOSE,
                                   AFS_REQUEST_FLAG_SYNCHRONOUS,
                                   &pCcb->AuthGroup,
                                   NULL,
                                   &stParentFileId,
                                   (void *)&stPIOCtlClose,
                                   sizeof( AFSPIOCtlOpenCloseRequestCB),
                                   NULL,
                                   NULL);

                pDirCB = pCcb->DirectoryCB;

                //
                // Remove the Ccb and de-allocate it
                //

                ntStatus = AFSRemoveCcb( pFcb,
                                         pCcb);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_WARNING,
                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);

                    //
                    // We can't actually fail a close operation so reset the status
                    //

                    ntStatus = STATUS_SUCCESS;
                }

                ASSERT( pDirCB->OpenReferenceCount > 0);

                InterlockedDecrement( &pDirCB->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (IOCtl) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                              &pDirCB->NameInformation.FileName,
                              pDirCB,
                              pCcb,
                              pDirCB->OpenReferenceCount);

                //
                // If this is not the root then decrement the open child reference count
                //

                if( pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose (IOCtl) Decrement child open ref count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
                }

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                ASSERT( pFcb->OpenReferenceCount != 0);

                InterlockedDecrement( &pFcb->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (IOCtl) Decrement count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenReferenceCount);

                break;
            }

            case AFS_ROOT_ALL:
            {

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Acquiring Special Root ALL lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

                pDirCB = pCcb->DirectoryCB;

                //
                // Remove the Ccb and de-allocate it
                //

                ntStatus = AFSRemoveCcb( pFcb,
                                         pCcb);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_WARNING,
                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);

                    //
                    // We can't actually fail a close operation so reset the status
                    //

                    ntStatus = STATUS_SUCCESS;
                }

                ASSERT( pDirCB->OpenReferenceCount > 0);

                InterlockedDecrement( &pDirCB->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Decrement (Root ALL) count on %wZ DE %p Ccb %p Cnt %d\n",
                              &pDirCB->NameInformation.FileName,
                              pDirCB,
                              pCcb,
                              pDirCB->OpenReferenceCount);

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                ASSERT( pFcb->OpenReferenceCount > 0);

                InterlockedDecrement( &pFcb->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (RootAll) Decrement count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenReferenceCount);

                break;
            }

            //
            // Root, file or directory node
            //

            case AFS_FILE_FCB:
            case AFS_ROOT_FCB:
            case AFS_DIRECTORY_FCB:
            case AFS_SYMBOLIC_LINK_FCB:
            case AFS_MOUNT_POINT_FCB:
            case AFS_DFS_LINK_FCB:
            case AFS_INVALID_FCB:
            {

                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

                //
                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Acquiring Dcb lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                KeQueryTickCount( &pFcb->ObjectInformation->LastAccessCount);

                pDirCB = pCcb->DirectoryCB;

                //
                // If this entry is deleted then remove the object from the volume tree
                //

                if( BooleanFlagOn( pDirCB->Flags, AFS_DIR_ENTRY_DELETED))
                {

                    if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
                    {

                        //
                        // Stop anything possibly in process
                        //

                        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSClose Acquiring Fcb extents lock %08lX EXCL %08lX\n",
                                      &pFcb->NPFcb->Specific.File.ExtentsResource,
                                      PsGetCurrentThread());

                        AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
                                        TRUE);

                        pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;

                        KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
                                    0,
                                    FALSE);

                        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSClose Releasing Fcb extents lock %08lX EXCL %08lX\n",
                                      &pFcb->NPFcb->Specific.File.ExtentsResource,
                                      PsGetCurrentThread());

                        AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
                    }

                    AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                    TRUE);

                    AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
                                    TRUE);

                    if ( pDirCB->OpenReferenceCount == 0)
                    {
                        AFSDbgLogMsg( 0,
                                      0,
                                      "AFSClose (Other) OpenReferenceCount is Zero on DE %08lX Ccb %08lX FileName %wZ\n",
                                      pDirCB,
                                      pCcb,
                                      &pDirCB->NameInformation.FileName);
                    }

                    ASSERT( pDirCB->OpenReferenceCount > 0);

                    InterlockedDecrement( &pDirCB->OpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose (Other) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                                  &pDirCB->NameInformation.FileName,
                                  pDirCB,
                                  pCcb,
                                  pDirCB->OpenReferenceCount);

                    if( pDirCB->OpenReferenceCount == 0)
                    {

                        AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSClose Deleting dir entry %08lX (%08lX) for %wZ  FID %08lX-%08lX-%08lX-%08lX\n",
                                      pDirCB,
                                      pObjectInfo,
                                      &pDirCB->NameInformation.FileName,
                                      pObjectInfo->FileId.Cell,
                                      pObjectInfo->FileId.Volume,
                                      pObjectInfo->FileId.Vnode,
                                      pObjectInfo->FileId.Unique);

                        //
                        // Remove and delete the directory entry from the parent list
                        //

                        AFSDeleteDirEntry( pObjectInfo->ParentObjectInformation,
                                           pDirCB);

                        if( pObjectInfo->ObjectReferenceCount == 0)
                        {

                            if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
                            {

                                AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
                                              AFS_TRACE_LEVEL_VERBOSE,
                                              "AFSClose Removing object %08lX from volume tree\n",
                                              pObjectInfo);

                                AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
                                                    &pObjectInfo->TreeEntry);

                                ClearFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
                            }

                            SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
                        }
                    }

                    AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);

                    AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
                }
                else
                {

                    ASSERT( pDirCB->OpenReferenceCount > 0);

                    InterlockedDecrement( &pDirCB->OpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose (Other2) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                                  &pDirCB->NameInformation.FileName,
                                  pDirCB,
                                  pCcb,
                                  pDirCB->OpenReferenceCount);
                }

                //
                // If this is not the root then decrement the open child reference count
                //

                if( pObjectInfo != NULL &&
                    pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose Decrement child open ref count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
                }

                if( pFcb->OpenReferenceCount == 1 &&
                    pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
                {

                    SetFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);

                    //
                    // Attempt to tear down our extent list for the file
                    // If there are remaining dirty extents then attempt to
                    // flush them as well
                    //

                    if( pFcb->Specific.File.ExtentsDirtyCount)
                    {

                        AFSFlushExtents( pFcb,
                                         &pCcb->AuthGroup);
                    }

                    //
                    // Wait for any outstanding queued flushes to complete
                    //

                    AFSWaitOnQueuedFlushes( pFcb);

                    ASSERT( pFcb->Specific.File.ExtentsDirtyCount == 0 &&
                            pFcb->Specific.File.QueuedFlushCount == 0);

                    AFSReleaseResource( &pFcb->NPFcb->Resource);

                    //
                    // Tear 'em down, we'll not be needing them again
                    //

                    if( AFSTearDownFcbExtents( pFcb,
                                               &pCcb->AuthGroup))
                    {

                        //
                        // Indicate to the service that the file required complete flushing to the
                        // server.
                        //

                        AFSProcessRequest( AFS_REQUEST_TYPE_FLUSH_FILE,
                                           AFS_REQUEST_FLAG_SYNCHRONOUS,
                                           &pCcb->AuthGroup,
                                           NULL,
                                           &pFcb->ObjectInformation->FileId,
                                           NULL,
                                           0,
                                           NULL,
                                           NULL);
                    }
                }
                else
                {

                    if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
                    {

                        if( pFcb->Specific.File.ExtentsDirtyCount)
                        {

                            AFSFlushExtents( pFcb,
                                             &pCcb->AuthGroup);
                        }
                    }

                    AFSReleaseResource( &pFcb->NPFcb->Resource);
                }

                //
                // Remove the Ccb and de-allocate it
                //

                ntStatus = AFSRemoveCcb( pFcb,
                                         pCcb);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_WARNING,
                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n",
                                  ntStatus);

                    //
                    // We can't actually fail a close operation so reset the status
                    //

                    ntStatus = STATUS_SUCCESS;
                }

                //
                // Decrement the reference count on the Fcb. this is protecting it from teardown.
                //

                ASSERT( pFcb->OpenReferenceCount != 0);

                InterlockedDecrement( &pFcb->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Decrement count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenReferenceCount);

                break;
            }

            case AFS_SPECIAL_SHARE_FCB:
            {

                AFSPipeOpenCloseRequestCB stPipeClose;

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Acquiring Special Share lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

                pDirCB = pCcb->DirectoryCB;

                RtlZeroMemory( &stPipeClose,
                               sizeof( AFSPipeOpenCloseRequestCB));

                stPipeClose.RequestId = pCcb->RequestID;

                stPipeClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;

                //
                // Issue the open request to the service
                //

                /*
                AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_CLOSE,
                                   AFS_REQUEST_FLAG_SYNCHRONOUS,
                                   &pFcb->AuthGroup,
                                   &pDirCB->NameInformation.FileName,
                                   NULL,
                                   (void *)&stPipeClose,
                                   sizeof( AFSPipeOpenCloseRequestCB),
                                   NULL,
                                   NULL);
                */

                //
                // Remove the Ccb and de-allocate it
                //

                ntStatus = AFSRemoveCcb( pFcb,
                                         pCcb);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_WARNING,
                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);

                    //
                    // We can't actually fail a close operation so reset the status
                    //

                    ntStatus = STATUS_SUCCESS;
                }

                ASSERT( pDirCB->OpenReferenceCount > 0);

                InterlockedDecrement( &pDirCB->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (Share) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                              &pDirCB->NameInformation.FileName,
                              pDirCB,
                              pCcb,
                              pDirCB->OpenReferenceCount);

                //
                // If this is not the root then decrement the open child reference count
                //

                if( pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose (Share) Decrement child open ref count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
                }

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                ASSERT( pFcb->OpenReferenceCount != 0);

                InterlockedDecrement( &pFcb->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (Share) Decrement count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenReferenceCount);

                break;
            }

            default:

                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSClose Processing unknown node type %d\n",
                              pFcb->Header.NodeTypeCode);

                break;
        }

try_exit:

        //
        // Complete the request
        //

        AFSCompleteRequest( Irp,
                            ntStatus);
    }
    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
    {

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

    return ntStatus;
}
Exemple #9
0
VOID
LfsWriteLfsRestart (
    IN PLFCB Lfcb,
    IN ULONG ThisRestartSize,
    IN BOOLEAN WaitForIo
    )

/*++

Routine Description:

    This routine puts the Lfs restart area on the queue of operations to
    write to the file.  We do this by allocating a second restart area
    and attaching it to the Lfcb.  We also allocate a buffer control
    block to use for this write.  We look at the WaitForIo boolean to
    determine whether this thread can perform the I/O.  This also indicates
    whether this thread gives up the Lfcb.

Arguments:

    Lfcb - A pointer to the log file control block for this operation.

    ThisRestartSize - This is the size to use for the restart area.

    WaitForIo - Indicates if this thread is to perform the work.

Return Value:

    None.

--*/

{
    PLBCB NewLbcb = NULL;
    PLFS_RESTART_AREA NewRestart = NULL;

    PAGED_CODE();

    DebugTrace( +1, Dbg, "LfsWriteLfsRestart:  Entered\n", 0 );
    DebugTrace(  0, Dbg, "Lfcb          -> %08lx\n", Lfcb );
    DebugTrace(  0, Dbg, "Write Chkdsk  -> %04x\n", WriteChkdsk );
    DebugTrace(  0, Dbg, "Restart Size  -> %08lx\n", ThisRestartSize );
    DebugTrace(  0, Dbg, "WaitForIo     -> %08lx\n", WaitForIo );

    //
    //  We'd absolutely hate for this to happen on a read only volume.
    //

    ASSERT(!(FlagOn( Lfcb->Flags, LFCB_READ_ONLY )));

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

    try {

        PLBCB ActiveLbcb;

        //
        //  We allocate another restart area and
        //  copy the current area into it.  Attach the new area to the Lfcb.
        //

        LfsAllocateRestartArea( &NewRestart, ThisRestartSize );

        //
        //  We allocate a Lbcb structure and update the values to
        //  reflect this restart area.
        //

        LfsAllocateLbcb( Lfcb, &NewLbcb );
        SetFlag( NewLbcb->LbcbFlags, LBCB_RESTART_LBCB );

        //
        //  If this is the second page, then add a page to the offset.
        //

        if (!Lfcb->InitialRestartArea) {

            NewLbcb->FileOffset = Lfcb->LogPageSize + NewLbcb->FileOffset;
        }

        (ULONG)NewLbcb->Length = ThisRestartSize;

        NewLbcb->PageHeader = (PVOID) Lfcb->RestartArea;

        //
        //  Lets put the current lsn in the Lbcb.
        //

        NewLbcb->LastEndLsn = NewLbcb->LastLsn = Lfcb->NextRestartLsn;
        Lfcb->NextRestartLsn.QuadPart = 1 + Lfcb->NextRestartLsn.QuadPart;

        //
        //  Copy the existing restart area into the new area.
        //

        RtlCopyMemory( NewRestart, Lfcb->RestartArea, ThisRestartSize );
        Lfcb->RestartArea = NewRestart;

        Lfcb->ClientArray = Add2Ptr( NewRestart, Lfcb->ClientArrayOffset, PLFS_CLIENT_RECORD );

        NewRestart = NULL;

        //
        //  Update the Lfcb to indicate that the other restart area
        //  on the disk is to be used.
        //

        Lfcb->InitialRestartArea = !Lfcb->InitialRestartArea;

        //
        //  Add this Lbcb to the end of the workque and flush to that point.
        //

        InsertTailList( &Lfcb->LbcbWorkque, &NewLbcb->WorkqueLinks );

        //
        //  If we don't support a packed log file then we need to make
        //  sure that all file records written out ahead of this
        //  restart area make it out to disk and we don't add anything
        //  to this page.
        //

        if (!FlagOn( Lfcb->Flags, LFCB_PACK_LOG )
            && !IsListEmpty( &Lfcb->LbcbActive )) {

            ActiveLbcb = CONTAINING_RECORD( Lfcb->LbcbActive.Flink,
                                            LBCB,
                                            ActiveLinks );

            if (FlagOn( ActiveLbcb->LbcbFlags, LBCB_NOT_EMPTY )) {

                RemoveEntryList( &ActiveLbcb->ActiveLinks );
                ClearFlag( ActiveLbcb->LbcbFlags, LBCB_ON_ACTIVE_QUEUE );
            }
        }

        if (WaitForIo) {

            LfsFlushLbcb( Lfcb, NewLbcb );
        }

    } finally {

        DebugUnwind( LfsWriteLfsRestart );

        if (NewRestart != NULL) {

            ExFreePool( NewRestart );
        }

        DebugTrace( -1, Dbg, "LfsWriteLfsRestart:  Exit\n", 0 );
    }

    return;
}
Exemple #10
0
__drv_mustHoldCriticalRegion    
NTSTATUS
FatCommonClose (
    IN PVCB Vcb,
    IN PFCB Fcb,
    IN PCCB Ccb,
    IN TYPE_OF_OPEN TypeOfOpen,
    IN BOOLEAN Wait,
    OUT PBOOLEAN VcbDeleted OPTIONAL
    )

/*++

Routine Description:

    This is the common routine for closing a file/directory called by both
    the fsd and fsp threads.

    Close is invoked whenever the last reference to a file object is deleted.
    Cleanup is invoked when the last handle to a file object is closed, and
    is called before close.

    The function of close is to completely tear down and remove the fcb/dcb/ccb
    structures associated with the file object.

Arguments:

    Fcb - Supplies the file to process.

    Wait - If this is TRUE we are allowed to block for the Vcb, if FALSE
        then we must try to acquire the Vcb anyway.

    VcbDeleted - Returns whether the VCB was deleted by this call.

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;
    PDCB ParentDcb;
    BOOLEAN RecursiveClose;
    BOOLEAN LocalVcbDeleted;
    IRP_CONTEXT IrpContext;

    PAGED_CODE();

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

    //
    //  Initailize the callers variable, if needed.
    //

    LocalVcbDeleted = FALSE;

    if (ARGUMENT_PRESENT( VcbDeleted )) {

        *VcbDeleted = LocalVcbDeleted;
    }

    //
    //  Special case the unopened file object
    //

    if (TypeOfOpen == UnopenedFileObject) {

        DebugTrace(0, Dbg, "Close unopened file object\n", 0);

        Status = STATUS_SUCCESS;

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

    //
    //  Set up our stack IrpContext.
    //

    RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) );

    IrpContext.NodeTypeCode = FAT_NTC_IRP_CONTEXT;
    IrpContext.NodeByteSize = sizeof( IrpContext );
    IrpContext.MajorFunction = IRP_MJ_CLOSE;
    IrpContext.Vcb = Vcb;
    
    if (Wait) {

        SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT );
    }

    //
    //  Acquire exclusive access to the Vcb and enqueue the irp if we didn't
    //  get access.
    //

#pragma prefast( suppress: 28137, "prefast wants Wait to be a constant, but that's not possible for fastfat" )
    if (!ExAcquireResourceExclusiveLite( &Vcb->Resource, Wait )) {

        return STATUS_PENDING;
    }

    //
    //  The following test makes sure that we don't blow away an Fcb if we
    //  are trying to do a Supersede/Overwrite open above us.  This test
    //  does not apply for the EA file.
    //

    if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS) &&
        Vcb->EaFcb != Fcb) {

        ExReleaseResourceLite( &Vcb->Resource );

        return STATUS_PENDING;
    }

    //
    //  Setting the following flag prevents recursive closes of directory file
    //  objects, which are handled in a special case loop.
    //

    if ( FlagOn(Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS) ) {

        RecursiveClose = TRUE;

    } else {

        SetFlag(Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS);
        RecursiveClose = FALSE;

        //
        //  Since we are at the top of the close chain, we need to add
        //  a reference to the VCB.  This will keep it from going away
        //  on us until we are ready to check for a dismount below.
        //

        Vcb->OpenFileCount += 1;
    }

    try {

        //
        //  Case on the type of open that we are trying to close.
        //

        switch (TypeOfOpen) {

        case VirtualVolumeFile:

            DebugTrace(0, Dbg, "Close VirtualVolumeFile\n", 0);

            //
            //  Remove this internal, residual open from the count.
            //

            InterlockedDecrement( (LONG*)&(Vcb->InternalOpenCount) );
            InterlockedDecrement( (LONG*)&(Vcb->ResidualOpenCount) );

            try_return( Status = STATUS_SUCCESS );
            break;

        case UserVolumeOpen:

            DebugTrace(0, Dbg, "Close UserVolumeOpen\n", 0);

            Vcb->DirectAccessOpenCount -= 1;
            Vcb->OpenFileCount -= 1;
            if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; }

            FatDeleteCcb( &IrpContext, &Ccb );

            try_return( Status = STATUS_SUCCESS );
            break;

        case EaFile:

            DebugTrace(0, Dbg, "Close EaFile\n", 0);

            //
            //  Remove this internal, residual open from the count.
            //

            InterlockedDecrement( (LONG*)&(Vcb->InternalOpenCount) );
            InterlockedDecrement( (LONG*)&(Vcb->ResidualOpenCount) );

            try_return( Status = STATUS_SUCCESS );
            break;

        case DirectoryFile:

            DebugTrace(0, Dbg, "Close DirectoryFile\n", 0);

            InterlockedDecrement( (LONG*)&Fcb->Specific.Dcb.DirectoryFileOpenCount );

            //
            //  Remove this internal open from the count.
            //

            InterlockedDecrement( (LONG*)&(Vcb->InternalOpenCount) );

            //
            //  If this is the root directory, it is a residual open
            //  as well.
            //

            if (NodeType( Fcb ) == FAT_NTC_ROOT_DCB) {

                InterlockedDecrement( (LONG*)&(Vcb->ResidualOpenCount) );
            }

            //
            //  If this is a recursive close, just return here.
            //

            if ( RecursiveClose ) {

                try_return( Status = STATUS_SUCCESS );

            } else {

                break;
            }

        case UserDirectoryOpen:
        case UserFileOpen:

            DebugTrace(0, Dbg, "Close UserFileOpen/UserDirectoryOpen\n", 0);

            //
            //  Uninitialize the cache map if we no longer need to use it
            //

            if ((NodeType(Fcb) == FAT_NTC_DCB) &&
                IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) &&
                (Fcb->OpenCount == 1) &&
                (Fcb->Specific.Dcb.DirectoryFile != NULL)) {

                PFILE_OBJECT DirectoryFileObject = Fcb->Specific.Dcb.DirectoryFile;

                DebugTrace(0, Dbg, "Uninitialize the stream file object\n", 0);

                CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );

                //
                //  Dereference the directory file.  This may cause a close
                //  Irp to be processed, so we need to do this before we destory
                //  the Fcb.
                //

                Fcb->Specific.Dcb.DirectoryFile = NULL;
                ObDereferenceObject( DirectoryFileObject );
            }

            Fcb->OpenCount -= 1;            
            Vcb->OpenFileCount -= 1;
            if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; }
           
            FatDeleteCcb( &IrpContext, &Ccb );

            break;

        default:

#pragma prefast( suppress: 28159, "if the type of open is unknown, we seriously messed up." )
            FatBugCheck( TypeOfOpen, 0, 0 );
        }

        //
        //  At this point we've cleaned up any on-disk structure that needs
        //  to be done, and we can now update the in-memory structures.
        //  Now if this is an unreferenced FCB or if it is
        //  an unreferenced DCB (not the root) then we can remove
        //  the fcb and set our ParentDcb to non null.
        //

        if (((NodeType(Fcb) == FAT_NTC_FCB) &&
             (Fcb->OpenCount == 0))

                ||

             ((NodeType(Fcb) == FAT_NTC_DCB) &&
              (IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue)) &&
              (Fcb->OpenCount == 0) &&
              (Fcb->Specific.Dcb.DirectoryFileOpenCount == 0))) {

            ParentDcb = Fcb->ParentDcb;

            SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );

            FatDeleteFcb( &IrpContext, &Fcb );

            //
            //  Uninitialize our parent's cache map if we no longer need
            //  to use it.
            //

            while ((NodeType(ParentDcb) == FAT_NTC_DCB) &&
                   IsListEmpty(&ParentDcb->Specific.Dcb.ParentDcbQueue) &&
                   (ParentDcb->OpenCount == 0) &&
                   (ParentDcb->Specific.Dcb.DirectoryFile != NULL)) {

                PFILE_OBJECT DirectoryFileObject;

                DirectoryFileObject = ParentDcb->Specific.Dcb.DirectoryFile;

                DebugTrace(0, Dbg, "Uninitialize our parent Stream Cache Map\n", 0);

                CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );

                ParentDcb->Specific.Dcb.DirectoryFile = NULL;

                ObDereferenceObject( DirectoryFileObject );

                //
                //  Now, if the ObDereferenceObject() caused the final close
                //  to come in, then blow away the Fcb and continue up,
                //  otherwise wait for Mm to to dereference its file objects
                //  and stop here..
                //

                if ( ParentDcb->Specific.Dcb.DirectoryFileOpenCount == 0) {

                    PDCB CurrentDcb;

                    CurrentDcb = ParentDcb;
                    ParentDcb = CurrentDcb->ParentDcb;

                    SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );

                    FatDeleteFcb( &IrpContext, &CurrentDcb );

                } else {

                    break;
                }
            }
        }

        Status = STATUS_SUCCESS;

    try_exit: NOTHING;
    } finally {

        DebugUnwind( FatCommonClose );

        //
        //  We are done processing the close.  If we are the top of the close
        //  chain, see if the VCB can go away.  We have biased the open count by
        //  one, so we need to take that into account.
        //

        if (!RecursiveClose) {

            //
            //  See if there is only one open left.  If so, it is ours.  We only want
            //  to check for a dismount if a dismount is not already in progress.
            //  We also only do this if the caller can handle the VCB going away.
            //  This is determined by whether they passed in the VcbDeleted argument.
            //

            if (Vcb->OpenFileCount == 1 &&
                !FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS )
                && ARGUMENT_PRESENT( VcbDeleted )) {

                //
                //  We need the global lock, which must be acquired before the
                //  VCB.  Since we already have the VCB, we have to drop and
                //  reaquire here.  Note that we always want to wait from this
                //  point on.  Note that the VCB cannot go away, since we have
                //  biased the open file count.
                //

                FatReleaseVcb( &IrpContext,
                               Vcb );

                SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT );

#pragma prefast( suppress: 28137, "prefast wants the wait parameter in this macro expansion to be a constant, unfortunately this is not possible" )
                FatAcquireExclusiveGlobal( &IrpContext );

                FatAcquireExclusiveVcb( &IrpContext,
                                        Vcb );

                //
                //  We have our locks in the correct order.  Remove our
                //  extra open and check for a dismount.  Note that if
                //  something changed while we dropped the lock, it will
                //  not matter, since the dismount code does the correct
                //  checks to make sure the volume can really go away.
                //

                Vcb->OpenFileCount -= 1;

                LocalVcbDeleted = FatCheckForDismount( &IrpContext,
                                                       Vcb,
                                                       FALSE );

                FatReleaseGlobal( &IrpContext );

                //
                //  Let the caller know what happened, if they want this information.
                //

                if (ARGUMENT_PRESENT( VcbDeleted )) {

                    *VcbDeleted = LocalVcbDeleted;
                }

            } else {

                //
                //  The volume cannot go away now.  Just remove our extra reference.
                //

                Vcb->OpenFileCount -= 1;
            }

            //
            //  If the VCB is still around, clear our recursion flag.
            //

            if (!LocalVcbDeleted) {

                ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS );
            }
        }

        //
        //  Only release the VCB if it did not go away.
        //

        if (!LocalVcbDeleted) {

            FatReleaseVcb( &IrpContext, Vcb );
        }

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

    return Status;
}
Exemple #11
0
VOID
FmmCloseMetadata (
    __in PFMM_INSTANCE_CONTEXT InstanceContext
    )
/*++

Routine Description:

    This routine closes the filters handle to the metadata file.

Arguments:

    InstanceContext - Instance context for this instance.

Return Value:

    Void.

Note:

    The caller must hold the instance context resource when this routine is called.


--*/
{
    PAGED_CODE();

    ASSERT( InstanceContext->MetadataHandle );
    ASSERT( InstanceContext->MetadataFileObject );

    DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                ("[Fmm]: Closing metadata file ... (Volume = %p)\n",
                 InstanceContext->Volume ) );

    //
    //  Dereference the file object and close the file handle.
    //

    ObDereferenceObject( InstanceContext->MetadataFileObject );

    InstanceContext->MetadataFileObject = NULL;


    //
    //  Mark the beginning of a file system operation
    //

    FmmBeginFileSystemOperation( InstanceContext );

    FltClose( InstanceContext->MetadataHandle );

    //
    //  Mark the end of a file system operation
    //

    FmmEndFileSystemOperation( InstanceContext );


    InstanceContext->MetadataHandle = NULL;

    //
    //  Reset flag to indicate filter metadata is closed
    //

    ClearFlag( InstanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED );

}
Exemple #12
0
NTSTATUS
Ext2ProcessVolumeProperty(
    IN  PEXT2_VCB              Vcb,
    IN  PEXT2_VOLUME_PROPERTY3 Property3,
    IN  ULONG Length
)
{
    struct nls_table * PageTable = NULL;
    PEXT2_VOLUME_PROPERTY2 Property2 = (PVOID)Property3;
    PEXT2_VOLUME_PROPERTY  Property = (PVOID)Property3;
    NTSTATUS Status = STATUS_SUCCESS;
    BOOLEAN VcbResourceAcquired = FALSE;

    _SEH2_TRY {

        ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
        VcbResourceAcquired = TRUE;

        if (Property->Command == APP_CMD_SET_PROPERTY ||
            Property->Command == APP_CMD_QUERY_PROPERTY) {
            if (Length < sizeof(EXT2_VOLUME_PROPERTY)) {
                Status = STATUS_INVALID_PARAMETER;
                _SEH2_LEAVE;
            }
        } else if (Property->Command == APP_CMD_SET_PROPERTY2 ||
                   Property->Command == APP_CMD_QUERY_PROPERTY2) {
            if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) {
                Status = STATUS_INVALID_PARAMETER;
                _SEH2_LEAVE;
            }
        } else if (Property->Command == APP_CMD_SET_PROPERTY3 ||
                   Property->Command == APP_CMD_QUERY_PROPERTY3) {
            if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) {
                Status = STATUS_INVALID_PARAMETER;
                _SEH2_LEAVE;
            }
        }

        switch (Property->Command) {

        case APP_CMD_SET_PROPERTY3:

            if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) {
                if (Property3->AutoMount)
                    SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
                else
                    ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
            }
            if (Property3->Flags2 & EXT2_VPROP3_USERIDS) {
                SetFlag(Vcb->Flags, VCB_USER_IDS);
                Vcb->uid = Property3->uid;
                Vcb->gid = Property3->gid;
                if (Property3->EIDS) {
                    Vcb->euid = Property3->euid;
                    Vcb->egid = Property3->egid;
                    SetFlag(Vcb->Flags, VCB_USER_EIDS);
                } else {
                    Vcb->euid = Vcb->egid = 0;
                    ClearFlag(Vcb->Flags, VCB_USER_EIDS);
                }
            } else {
                ClearFlag(Vcb->Flags, VCB_USER_IDS);
                ClearFlag(Vcb->Flags, VCB_USER_EIDS);
                Vcb->uid = Vcb->gid = 0;
                Vcb->euid = Vcb->egid = 0;
            }

        case APP_CMD_SET_PROPERTY2:

            RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN);
            if (Vcb->bHidingPrefix == Property2->bHidingPrefix) {
                RtlCopyMemory( Vcb->sHidingPrefix,
                               Property2->sHidingPrefix,
                               HIDINGPAT_LEN - 1);
            }

            RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN);
            if (Vcb->bHidingSuffix == Property2->bHidingSuffix) {
                RtlCopyMemory( Vcb->sHidingSuffix,
                               Property2->sHidingSuffix,
                               HIDINGPAT_LEN - 1);
            }
            Vcb->DrvLetter = Property2->DrvLetter;

        case APP_CMD_SET_PROPERTY:

            if (Property->bReadonly) {
                if (IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) {
                    Ext2FlushFiles(NULL, Vcb, FALSE);
                    Ext2FlushVolume(NULL, Vcb, FALSE);
                }
                SetLongFlag(Vcb->Flags, VCB_READ_ONLY);

            } else {

                if (Property->bExt3Writable) {
                    SetLongFlag(Vcb->Flags, VCB_FORCE_WRITING);
                }

                if (!Vcb->IsExt3fs) {
                    ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
                } else if (!Property->bExt3Writable) {
                    SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
                } else if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) {
                    ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
                    Ext2RecoverJournal(NULL, Vcb);
                    if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) {
                        SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
                    } else {
                        ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
                    }
                } else {
                    ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
                }
            }

            PageTable = load_nls(Property->Codepage);
            memcpy(Vcb->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN);
            Vcb->Codepage.PageTable = PageTable;
            if (Vcb->Codepage.PageTable) {
                Ext2InitializeLabel(Vcb, Vcb->SuperBlock);
            }

            break;

        case APP_CMD_QUERY_PROPERTY3:

            if (IsFlagOn(Ext2Global->Flags, EXT2_AUTO_MOUNT)) {
                SetFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT);
                Property3->AutoMount = TRUE;
            } else {
                ClearFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT);
                Property3->AutoMount = FALSE;
            }

            if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) {
                SetFlag(Property3->Flags2, EXT2_VPROP3_USERIDS);
                Property3->uid = Vcb->uid;
                Property3->gid = Vcb->gid;
                if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) {
                    Property3->EIDS = TRUE;
                    Property3->euid = Vcb->euid;
                    Property3->egid = Vcb->egid;
                } else {
                    Property3->EIDS = FALSE;
                }
            } else {
                ClearFlag(Property3->Flags2, EXT2_VPROP3_USERIDS);
            }

        case APP_CMD_QUERY_PROPERTY2:

            RtlCopyMemory(Property2->UUID, Vcb->SuperBlock->s_uuid, 16);
            Property2->DrvLetter = Vcb->DrvLetter;

            if (Property2->bHidingPrefix == Vcb->bHidingPrefix) {
                RtlCopyMemory( Property2->sHidingPrefix,
                               Vcb->sHidingPrefix,
                               HIDINGPAT_LEN);
            } else {
                RtlZeroMemory( Property2->sHidingPrefix,
                               HIDINGPAT_LEN);
            }

            if (Property2->bHidingSuffix == Vcb->bHidingSuffix) {
                RtlCopyMemory( Property2->sHidingSuffix,
                               Vcb->sHidingSuffix,
                               HIDINGPAT_LEN);
            } else {
                RtlZeroMemory( Property2->sHidingSuffix,
                               HIDINGPAT_LEN);
            }

        case APP_CMD_QUERY_PROPERTY:

            Property->bExt2 = TRUE;
            Property->bExt3 = Vcb->IsExt3fs;
            Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY);
            if (!Property->bReadonly && Vcb->IsExt3fs) {
                Property->bExt3Writable = TRUE;
            } else {
                Property->bExt3Writable = FALSE;
            }

            RtlZeroMemory(Property->Codepage, CODEPAGE_MAXLEN);
            if (Vcb->Codepage.PageTable) {
                strncpy(Property->Codepage, Vcb->Codepage.PageTable->charset, CODEPAGE_MAXLEN);
            } else {
                strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN);
            }
            break;

        default:
            Status = STATUS_INVALID_PARAMETER;
            break;
        }

    } _SEH2_FINALLY {

        if (VcbResourceAcquired) {
            ExReleaseResourceLite(&Vcb->MainResource);
        }
    } _SEH2_END;

    return Status;
}
NTSTATUS
NdasFatCommonFlushBuffers (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for flushing a buffer.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;

    PIO_STACK_LOCATION IrpSp;

    PFILE_OBJECT FileObject;

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

    BOOLEAN VcbAcquired = FALSE;
    BOOLEAN FcbAcquired = FALSE;

    PDIRENT Dirent;
    PBCB DirentBcb = NULL;

	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;

	PSECONDARY_REQUEST			secondaryRequest = NULL;

	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;

	LARGE_INTEGER				timeOut;


    PAGED_CODE();

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace(+1, Dbg, "FatCommonFlushBuffers\n", 0);
    DebugTrace( 0, Dbg, "Irp           = %08lx\n", Irp);
    DebugTrace( 0, Dbg, "->FileObject  = %08lx\n", IrpSp->FileObject);

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

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

    //
    //  CcFlushCache is always synchronous, so if we can't wait enqueue
    //  the irp to the Fsp.
    //

    if ( !FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ) {

        Status = FatFsdPostRequest( IrpContext, Irp );

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

    Status = STATUS_SUCCESS;

    try {

		if (!FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

			do {
			
				secondarySessionResourceAcquired 
					= SecondaryAcquireResourceExclusiveLite( IrpContext, 
															 &volDo->SessionResource, 
															 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

				if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

					PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp );
					NDAS_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
					SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST );
					FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );	
				}

				secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, IRP_MJ_FLUSH_BUFFERS, 0 );

				if (secondaryRequest == NULL) {
	
					NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES );
					Status = STATUS_INSUFFICIENT_RESOURCES;
					break;
				}

				ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;

				INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_FLUSH_BUFFERS, 0 );

				ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
				ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

				INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, 
													  IrpContext->OriginatingIrp, 
													  IoGetCurrentIrpStackLocation(IrpContext->OriginatingIrp), 
													  Ccb->PrimaryFileHandle );
				
				ASSERT( !ExIsResourceAcquiredSharedLite(&IrpContext->Vcb->Resource) );	

				secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
				QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

				timeOut.QuadPart = -NDASFAT_TIME_OUT;		
				Status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );
			
				if (Status != STATUS_SUCCESS) {

					ASSERT( NDASFAT_BUG );
					break;
				}

				KeClearEvent (&secondaryRequest->CompleteEvent);

				if (BooleanFlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {

					NDAS_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
					SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST );
					FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
				}

				if (secondaryRequest->ExecuteStatus == STATUS_SUCCESS) {

					ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
					ASSERT(NTOHL(ndfsWinxpReplytHeader->Status4) == STATUS_SUCCESS);
				}

				if (secondaryRequest) {

					DereferenceSecondaryRequest( secondaryRequest );
					secondaryRequest = NULL;
				}

				if ( secondarySessionResourceAcquired == TRUE ) {
					
					SecondaryReleaseResourceLite( IrpContext, &volDo->SessionResource );		
					secondarySessionResourceAcquired = FALSE;
				}

				break;

			} while(0);
		} 

		Status = STATUS_SUCCESS;

        //
        //  Case on the type of open that we are trying to flush
        //

        switch (TypeOfOpen) {

        case VirtualVolumeFile:
        case EaFile:
        case DirectoryFile:

            DebugTrace(0, Dbg, "Flush that does nothing\n", 0);
            break;

        case UserFileOpen:

            DebugTrace(0, Dbg, "Flush User File Open\n", 0);

            (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );

            FcbAcquired = TRUE;

            FatVerifyFcb( IrpContext, Fcb );

            //
            //  If the file is cached then flush its cache
            //

            Status = FatFlushFile( IrpContext, Fcb, Flush );

            //
            //  Also update and flush the file's dirent in the parent directory if the
            //  file flush worked.
            //

            if (NT_SUCCESS( Status )) {

                //
                //  Insure that we get the filesize to disk correctly.  This is
                //  benign if it was already good.
                //
                //  (why do we need to do this?)
                //

                SetFlag(FileObject->Flags, FO_FILE_SIZE_CHANGED);

#if 0
                FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
#endif                
                
                //
                //  Flush the volume file to get any allocation information
                //  updates to disk.
                //

                if (FlagOn(Fcb->FcbState, FCB_STATE_FLUSH_FAT)) {

                    Status = FatFlushFat( IrpContext, Vcb );

                    ClearFlag(Fcb->FcbState, FCB_STATE_FLUSH_FAT);
                }

                //
                //  Set the write through bit so that these modifications
                //  will be completed with the request.
                //

                SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
            }

            break;

        case UserDirectoryOpen:

            //
            //  If the user had opened the root directory then we'll
            //  oblige by flushing the volume.
            //

            if (NodeType(Fcb) != FAT_NTC_ROOT_DCB) {

                DebugTrace(0, Dbg, "Flush a directory does nothing\n", 0);
                break;
            }

        case UserVolumeOpen:

            DebugTrace(0, Dbg, "Flush User Volume Open, or root dcb\n", 0);

            //
            //  Acquire exclusive access to the Vcb.
            //

            {
                BOOLEAN Finished;
                Finished = FatAcquireExclusiveVcb( IrpContext, Vcb );
                ASSERT( Finished );
            }

            VcbAcquired = TRUE;

            //
            //  Mark the volume clean and then flush the volume file,
            //  and then all directories
            //

            Status = FatFlushVolume( IrpContext, Vcb, Flush );

            //
            //  If the volume was dirty, do the processing that the delayed
            //  callback would have done.
            //

            if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY)) {

                //
                //  Cancel any pending clean volumes.
                //

                (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
                (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );

                //
                //  The volume is now clean, note it.
                //

                if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {

                    FatMarkVolume( IrpContext, Vcb, VolumeClean );
                    ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY );
                }

                //
                //  Unlock the volume if it is removable.
                //

                if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
                    !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE)) {

                    FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
                }
            }

            break;

        default:

            FatBugCheck( TypeOfOpen, 0, 0 );
        }

        FatUnpinBcb( IrpContext, DirentBcb );

        FatUnpinRepinnedBcbs( IrpContext );

    } finally {

        DebugUnwind( FatCommonFlushBuffers );

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );

		if (secondarySessionResourceAcquired) {

			SecondaryReleaseResourceLite( IrpContext, &volDo->SessionResource );		
		}

        FatUnpinBcb( IrpContext, DirentBcb );

        if (VcbAcquired) { FatReleaseVcb( IrpContext, Vcb ); }

        if (FcbAcquired) { FatReleaseFcb( IrpContext, Fcb ); }

        //
        //  If this is a normal termination then pass the request on
        //  to the target device object.
        //

        if (!AbnormalTermination()) {

            NTSTATUS DriverStatus;
            PIO_STACK_LOCATION NextIrpSp;

            //
            //  Get the next stack location, and copy over the stack location
            //

            NextIrpSp = IoGetNextIrpStackLocation( Irp );

            *NextIrpSp = *IrpSp;

            //
            //  Set up the completion routine
            //

            IoSetCompletionRoutine( Irp,
                                    FatFlushCompletionRoutine,
                                    ULongToPtr( Status ),
                                    TRUE,
                                    TRUE,
                                    TRUE );

            //
            //  Send the request.
            //

            DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);

            Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
                     Status : DriverStatus;

            //
            //  Free the IrpContext and return to the caller.
            //

            FatCompleteRequest( IrpContext, FatNull, STATUS_SUCCESS );
        }

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

    return Status;
}
Exemple #14
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;
}
static
DWORD
LsaAdBatchBuilderBatchItemGetAttributeValue(
    IN PAD_PROVIDER_DATA pProviderData,
    IN PVOID pCallbackContext,
    IN PVOID pItem,
    OUT PCSTR* ppszValue,
    OUT PVOID* ppFreeValueContext
    )
{
    DWORD dwError = 0;
    PLSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT pContext = (PLSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT)pCallbackContext;
    LSA_AD_BATCH_QUERY_TYPE QueryType = pContext->QueryType;
    BOOLEAN bIsForRealObject = pContext->bIsForRealObject;
    PLSA_LIST_LINKS pLinks = (PLSA_LIST_LINKS)pItem;
    PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);
    PSTR pszValueToEscape = NULL;
    PSTR pszValueToHex = NULL;
    PSTR pszValue = NULL;
    PVOID pFreeValueContext = NULL;
    // Free this on error only.
    PSTR pszMatchTerm = NULL;
    PSTR pszAllocatedMatchTermValue = NULL;
    BOOLEAN bHaveReal = IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_REAL);
    BOOLEAN bHavePseudo = IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_PSEUDO);

    if (IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM))
    {
        LW_SAFE_FREE_STRING(pBatchItem->pszQueryMatchTerm);
        ClearFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM);
    }

    if ((bIsForRealObject && bHaveReal) ||
        (!bIsForRealObject && bHavePseudo))
    {
        // This can only happen in the linked cells case, but even
        // that should go away in the future as we just keep an
        // unresolved batch items list.

        LSA_ASSERT(!bIsForRealObject && (pProviderData->dwDirectoryMode == CELL_MODE));
        goto cleanup;
    }

    switch (QueryType)
    {
        case LSA_AD_BATCH_QUERY_TYPE_BY_DN:
            // Must be looking for real object
            LSA_ASSERT(bIsForRealObject);
            LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type);

            pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString;
            LSA_ASSERT(pszValueToEscape);
            break;

        case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
            if (pBatchItem->pszSid)
            {
                // This is case where we already got the SID by resolving
                // the pseudo object by id/alias.
                pszValue = pBatchItem->pszSid;
            }
            else if (QueryType == pBatchItem->QueryTerm.Type)
            {
                // This is the case where the original query was
                // a query by SID.
                pszValue = (PSTR)pBatchItem->QueryTerm.pszString;
                LSA_ASSERT(pszValue);
            }
            // Will be NULL if we cannot find a SID for which to query.
            // This can happen if this batch item is for an object
            // that we did not find real but are trying to look up pseudo.
            // In that case, we have NULL and will just skip it.

            // If we have a SID string, make sure it looks like a SID.
            // Note that we must do some sanity checking to make sure
            // that the string does not need escaping since we are
            // not setting pszValueToEscape.  (The SID check takes
            // care of that.)
            if (pszValue && !LsaAdBatchHasValidCharsForSid(pszValue))
            {
                LSA_ASSERT(FALSE);
                dwError = LW_ERROR_INTERNAL;
                BAIL_ON_LSA_ERROR(dwError);
            }

            if (bIsForRealObject)
            {
                // "S-"-style SID string are only handled starting with
                // Windows 2003.  So an LDAP hex-formatted SID string
                // is needed to handle Windows 2000.

                pszValueToHex = pszValue;
                pszValue = NULL;
            }
            break;

        case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
            LSA_ASSERT(bIsForRealObject);
            if (pBatchItem->pszSamAccountName)
            {
                // Unprovisioned id/alias case where id mapper returned
                // a SAM account name (and domain name) but no SID.
                pszValueToEscape = pBatchItem->pszSamAccountName;
                // However, we currently do not have this sort of id mapper
                // support, so we LSA_ASSERT(FALSE) for now.
                LSA_ASSERT(FALSE);
            }
            else if (QueryType == pBatchItem->QueryTerm.Type)
            {
                pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString;
                LSA_ASSERT(pszValueToEscape);
            }
            break;

        case LSA_AD_BATCH_QUERY_TYPE_BY_UID:
        case LSA_AD_BATCH_QUERY_TYPE_BY_GID:
            LSA_ASSERT(!bIsForRealObject);
            LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type);

            dwError = LwAllocateStringPrintf(
                            &pszAllocatedMatchTermValue,
                            "%u",
                            (unsigned int)pBatchItem->QueryTerm.dwId);
            BAIL_ON_LSA_ERROR(dwError);
            pszValue = pszAllocatedMatchTermValue;

            // Note: It is ok to set this here because it is ok for
            // this flag to be set if the match term field in the
            // batch item is still NULL (i.e., if we fail later in
            // this function).
            SetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM);

            break;

        case LSA_AD_BATCH_QUERY_TYPE_BY_USER_ALIAS:
        case LSA_AD_BATCH_QUERY_TYPE_BY_GROUP_ALIAS:
            LSA_ASSERT(!bIsForRealObject);
            LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type);

            pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString;
            LSA_ASSERT(pszValueToEscape);
            break;

        default:
            dwError = LW_ERROR_INVALID_PARAMETER;
            BAIL_ON_LSA_ERROR(dwError);
    }

    LSA_ASSERT(!pszMatchTerm);
    LSA_ASSERT(!(pszValueToEscape && pszValueToHex));

    if (pszValueToEscape)
    {
        LSA_ASSERT(!pszValue);
        dwError = LwLdapEscapeString(&pszValue, pszValueToEscape);
        BAIL_ON_LSA_ERROR(dwError);

        pszMatchTerm = pszValueToEscape;
        pFreeValueContext = pszValue;
    }
    else if (pszValueToHex)
    {
        LSA_ASSERT(!pszValue);
        dwError = LsaSidStrToLdapFormatHexStr(pszValueToHex, &pszValue);
        BAIL_ON_LSA_ERROR(dwError);

        pszMatchTerm = pszValueToHex;
        pFreeValueContext = pszValue;
    }
    else
    {
        pszMatchTerm = pszValue;
    }

cleanup:
    // Note that the match value can be different from the value,
    // which we may need to escape or hex.
    pBatchItem->pszQueryMatchTerm = pszMatchTerm;
    *ppszValue = pszValue;
    *ppFreeValueContext = pFreeValueContext;

    return dwError;

error:
    // assing output in cleanup in case of goto cleanup in function.
    pszValueToEscape = NULL;
    pszValue = NULL;
    LW_SAFE_FREE_STRING(pFreeValueContext);
    LW_SAFE_FREE_STRING(pszAllocatedMatchTermValue);
    goto cleanup;
}
Exemple #16
0
NTSTATUS
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS                Status = STATUS_SUCCESS;

    PIRP                    Irp = NULL;
    PIO_STACK_LOCATION      IrpSp = NULL;

    PEXT2_VCB               Vcb = NULL;
    PEXT2_FCB               Fcb = NULL;
    PEXT2_FCBVCB            FcbOrVcb = NULL;
    PEXT2_CCB               Ccb = NULL;
    PFILE_OBJECT            FileObject = NULL;

    PDEVICE_OBJECT          DeviceObject = NULL;

    BOOLEAN                 MainResourceAcquired = FALSE;

    _SEH2_TRY {

        ASSERT(IrpContext);

        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;

        //
        // This request is not allowed on the main device object
        //
        if (IsExt2FsDevice(DeviceObject)) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            _SEH2_LEAVE;
        }

        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        ASSERT(IsMounted(Vcb));
        if (IsVcbReadOnly(Vcb)) {
            Status =  STATUS_SUCCESS;
            _SEH2_LEAVE;
        }

        Irp = IrpContext->Irp;
        IrpSp = IoGetCurrentIrpStackLocation(Irp);

        FileObject = IrpContext->FileObject;
        FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
        ASSERT(FcbOrVcb != NULL);

        Ccb = (PEXT2_CCB) FileObject->FsContext2;
        if (Ccb == NULL) {
            Status =  STATUS_SUCCESS;
            _SEH2_LEAVE;
        }

        MainResourceAcquired =
            ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE);
        ASSERT(MainResourceAcquired);
        DEBUG(DL_INF, ("Ext2Flush-pre:  total mcb records=%u\n",
                       FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));

        if (FcbOrVcb->Identifier.Type == EXT2VCB) {

            Ext2VerifyVcb(IrpContext, Vcb);
            Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
            if (NT_SUCCESS(Status)) {
                _SEH2_LEAVE;
            }

            Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);

            if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
                ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
            }

        } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {

            Fcb = (PEXT2_FCB)(FcbOrVcb);

            Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
            if (NT_SUCCESS(Status)) {
                if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
                    Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
                    ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
                }
            }
        }

        DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
                       FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));


    } _SEH2_FINALLY {

        if (MainResourceAcquired) {
            ExReleaseResourceLite(&FcbOrVcb->MainResource);
        }

        if (!IrpContext->ExceptionInProgress) {

            if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) {

                // Call the disk driver to flush the physial media.
                NTSTATUS DriverStatus;
                PIO_STACK_LOCATION NextIrpSp;

                NextIrpSp = IoGetNextIrpStackLocation(Irp);

                *NextIrpSp = *IrpSp;

                IoSetCompletionRoutine( Irp,
                                        Ext2FlushCompletionRoutine,
                                        NULL,
                                        TRUE,
                                        TRUE,
                                        TRUE );

                DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);

                Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
                         Status : DriverStatus;

                IrpContext->Irp = Irp = NULL;
            }

            Ext2CompleteIrpContext(IrpContext, Status);
        }
    } _SEH2_END;

    return Status;
}
DWORD
LsaAdBatchBuildQueryForRpc(
    IN PCSTR pszNetbiosDomainName,
    IN LSA_AD_BATCH_QUERY_TYPE QueryType,
    // List of PLSA_AD_BATCH_ITEM
    IN PLSA_LIST_LINKS pFirstLinks,
    IN PLSA_LIST_LINKS pEndLinks,
    OUT PLSA_LIST_LINKS* ppNextLinks,
    IN DWORD dwMaxQueryCount,
    OUT PDWORD pdwQueryCount,
    OUT PSTR** pppszQueryList
    )
{
    DWORD dwError = 0;
    PLSA_LIST_LINKS pLinks = NULL;
    PSTR* ppszQueryList = NULL;
    PLSA_LIST_LINKS pLastLinks = pFirstLinks;
    DWORD dwQueryCount = 0;
    DWORD dwSavedQueryCount = 0;

    pLinks = pFirstLinks;
    for (pLinks = pFirstLinks; pLinks != pEndLinks; pLinks = pLinks->Next)
    {
        PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);
        PCSTR pszQueryTerm = NULL;

        switch (QueryType)
        {
            case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
            {
                if (pBatchItem->pszSid)
                {
                    pszQueryTerm = pBatchItem->pszSid;
                }
                else if (QueryType == pBatchItem->QueryTerm.Type)
                {
                    pszQueryTerm = pBatchItem->QueryTerm.pszString;
                }
                break;
            }
            case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
            {
                if (pBatchItem->pszSamAccountName)
                {
                    pszQueryTerm = pBatchItem->pszSamAccountName;
                }
                else if (QueryType == pBatchItem->QueryTerm.Type)
                {
                    pszQueryTerm = pBatchItem->QueryTerm.pszString;
                }
                break;
            }
            default:
                LSA_ASSERT(FALSE);
                dwError = LW_ERROR_INTERNAL;
                BAIL_ON_LSA_ERROR(dwError);
        }

        if (!LW_IS_NULL_OR_EMPTY_STR(pszQueryTerm))
        {
            DWORD dwNewQueryCount = dwQueryCount + 1;

            if (dwMaxQueryCount && (dwNewQueryCount > dwMaxQueryCount))
            {
                break;
            }
            dwQueryCount = dwNewQueryCount;
        }
    }
    pLastLinks = pLinks;
    dwSavedQueryCount = dwQueryCount;

    if (dwQueryCount < 1)
    {
        goto cleanup;
    }

    dwError = LwAllocateMemory(dwQueryCount*sizeof(*ppszQueryList), (PVOID*)&ppszQueryList);
    BAIL_ON_LSA_ERROR(dwError);

    dwQueryCount = 0;
    // Loop until we reach last links.
    for (pLinks = pFirstLinks; pLinks != pLastLinks; pLinks = pLinks->Next)
    {
        PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);

        if (IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM))
        {
            LW_SAFE_FREE_STRING(pBatchItem->pszQueryMatchTerm);
            ClearFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM);
        }

        switch (QueryType)
        {
            case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
            {
                PCSTR pszUseSid = NULL;
                if (pBatchItem->pszSid)
                {
                    pszUseSid = pBatchItem->pszSid;
                }
                else if (QueryType == pBatchItem->QueryTerm.Type)
                {
                    pszUseSid = pBatchItem->QueryTerm.pszString;
                }
                // We might not have a SID if we failed to find a pseudo.
                if (pszUseSid)
                {
                    dwError = LwAllocateString(pszUseSid,
                                                &ppszQueryList[dwQueryCount++]);
                    BAIL_ON_LSA_ERROR(dwError);
                    pBatchItem->pszQueryMatchTerm = (PSTR)pszUseSid;
                }
                break;
            }

            case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
            {
                PCSTR pszUseSamAccountName = NULL;
                if (pBatchItem->pszSamAccountName)
                {
                    pszUseSamAccountName = pBatchItem->pszSamAccountName;
                }
                else if (QueryType == pBatchItem->QueryTerm.Type)
                {
                    pszUseSamAccountName = pBatchItem->QueryTerm.pszString;
                }
                if (pszUseSamAccountName)
                {
                    dwError = LwAllocateStringPrintf(
                                    &ppszQueryList[dwQueryCount++],
                                    "%s\\%s",
                                    pszNetbiosDomainName,
                                    pszUseSamAccountName);
                    BAIL_ON_LSA_ERROR(dwError);
                    pBatchItem->pszQueryMatchTerm = (PSTR)pszUseSamAccountName;
                }
                break;
            }
            default:
                LSA_ASSERT(FALSE);
                dwError = LW_ERROR_INTERNAL;
                BAIL_ON_LSA_ERROR(dwError);
        }
    }

    assert(dwSavedQueryCount == dwQueryCount);

cleanup:
    // We handle error here instead of error label
    // because there is a goto cleanup above.
    if (dwError)
    {
        LwFreeStringArray(ppszQueryList, dwSavedQueryCount);
        ppszQueryList = NULL;
        dwQueryCount = 0;
        dwSavedQueryCount = 0;
        pLastLinks = pFirstLinks;
    }

    *pppszQueryList = ppszQueryList;
    *pdwQueryCount = dwQueryCount;
    *ppNextLinks = pLastLinks;

    return dwError;

error:
    // Do not actually handle any errors here.
    goto cleanup;
}
Exemple #18
0
int flows2nfdump(struct ftio *ftio, char *wfile, int compress, extension_info_t *extension_info, int extended, uint32_t limitflows) {
// required flow tools variables
struct fttime 		ftt;
struct fts3rec_offsets fo;
struct ftver 		ftv;
char				*rec;
// nfdump variables
nffile_t			*nffile;
master_record_t	 record;
char				*s;
uint32_t			cnt;

	s = "flow-tools";
	nffile = OpenNewFile( wfile , NULL, compress, 0, s);
	if ( !nffile ) {
		fprintf(stderr, "%s\n", s);
		return 1;
	}

	AppendToBuffer(nffile, (void *)extension_info->map, extension_info->map->size);
	
	ftio_get_ver(ftio, &ftv);
	fts3rec_compute_offsets(&fo, &ftv);

	memset((void *)&record, 0, sizeof(record));
	record.map_ref 		  = extension_info->map;
	record.type 		  = CommonRecordType;
	record.exporter_sysid = 0;

	// only v4 addresses
	ClearFlag(record.flags, FLAG_IPV6_ADDR);

	cnt = 0;
	while ((rec = ftio_read(ftio))) {
		uint32_t when, unix_secs, unix_nsecs, sysUpTime;
		int i, id;

		unix_secs  = *((uint32_t*)(rec+fo.unix_secs));
		unix_nsecs = *((uint32_t*)(rec+fo.unix_nsecs));
		sysUpTime  = *((uint32_t*)(rec+fo.sysUpTime));

		when	   = *((uint32_t*)(rec+fo.First));
		ftt = ftltime(sysUpTime, unix_secs, unix_nsecs, when);
		record.first 		= ftt.secs;
		record.msec_first 	= ftt.msecs;
	
		when	   = *((uint32_t*)(rec+fo.Last));
		ftt = ftltime(sysUpTime, unix_secs, unix_nsecs, when);
		record.last 		= ftt.secs;
		record.msec_last 	= ftt.msecs;
	
		record.v4.srcaddr 	= *((uint32_t*)(rec+fo.srcaddr));
		record.v4.dstaddr 	= *((uint32_t*)(rec+fo.dstaddr));
		record.srcport 		= *((uint16_t*)(rec+fo.srcport));
		record.dstport 		= *((uint16_t*)(rec+fo.dstport));

		record.prot 		= *((uint8_t*)(rec+fo.prot));
		record.tcp_flags	= *((uint8_t*)(rec+fo.tcp_flags));
		record.tos 			= *((uint8_t*)(rec+fo.tos));

		record.dOctets 		= *((uint32_t*)(rec+fo.dOctets));
		record.dPkts 		= *((uint32_t*)(rec+fo.dPkts));

		i = 0;
		while ( (id = extension_info->map->ex_id[i]) != 0 ) {
			switch (id) {
				case EX_IO_SNMP_2:
					record.input 		= *((uint16_t*)(rec+fo.input));
					record.output 		= *((uint16_t*)(rec+fo.output));
					break;
				case EX_AS_2:
					record.srcas 		= *((uint16_t*)(rec+fo.src_as));
					record.dstas 		= *((uint16_t*)(rec+fo.dst_as));
					break;
				case EX_MULIPLE:
    				record.src_mask 	= *((uint8_t*)(rec+fo.src_mask));
    				record.dst_mask 	= *((uint8_t*)(rec+fo.dst_mask));
					record.dir			= 0;
					record.dst_tos  	= 0;
					break;
				case EX_ROUTER_IP_v4:
					record.ip_nexthop.v4 = *((uint32_t*)(rec+fo.peer_nexthop));
					break;
				case EX_NEXT_HOP_v4:
					record.ip_router.v4 = *((uint32_t*)(rec+fo.router_sc));
					break;
				case EX_ROUTER_ID:
					record.engine_type = *((uint8_t*)(rec+fo.engine_type));
					record.engine_id   = *((uint8_t*)(rec+fo.engine_id));
					break;
				// default: Other extensions can not be sent with v5
			}
			i++;
		}

		PackRecord(&record, nffile);

		if ( extended ) {
			char *string;
			format_file_block_record(&record, &string, 0);
			fprintf(stderr, "%s\n", string);
		} 

		cnt++;
		if ( cnt == limitflows )
			break;

	} /* while */

	// write the last records in buffer
	if ( nffile->block_header->NumRecords ) {
		if ( WriteBlock(nffile) <= 0 ) {
			fprintf(stderr, "Failed to write output buffer: '%s'" , strerror(errno));
		} 
	}

	free((void *)extension_info->map);
	free((void *)extension_info);
	DisposeFile(nffile);

	return 0;

} // End of flows2nfdump
TYPE_OF_OPEN
CdDecodeFileObject (
    _In_ PIRP_CONTEXT IrpContext,
    _In_ PFILE_OBJECT FileObject,
    PFCB *Fcb,
    PCCB *Ccb
)

/*++

Routine Description:

    This routine takes a file object and extracts the Fcb and Ccb (possibly NULL)
    and returns the type of open.

Arguments:

    FileObject - Supplies the file object pointer being initialized.

    Fcb - Address to store the Fcb contained in the file object.

    Ccb - Address to store the Ccb contained in the file object.

Return Value:

    TYPE_OF_OPEN - Indicates the type of file object.

--*/

{
    TYPE_OF_OPEN TypeOfOpen;

    PAGED_CODE();

    UNREFERENCED_PARAMETER( IrpContext );

    //
    //  If this is an unopened file object then return NULL for the
    //  Fcb/Ccb.  Don't trust any other values in the file object.
    //

    TypeOfOpen = (TYPE_OF_OPEN) FlagOn( (ULONG_PTR) FileObject->FsContext2,
                                        TYPE_OF_OPEN_MASK );

    if (TypeOfOpen == UnopenedFileObject) {

        *Fcb = NULL;
        *Ccb = NULL;

    } else {

        //
        //  The Fcb is pointed to by the FsContext field.  The Ccb is in
        //  FsContext2 (after clearing the low three bits).  The low three
        //  bits are the file object type.
        //

        *Fcb = FileObject->FsContext;
        *Ccb = FileObject->FsContext2;

#pragma warning( suppress: 4213 )
        ClearFlag( (ULONG_PTR) *Ccb, TYPE_OF_OPEN_MASK );
    }

    //
    //  Now return the type of open.
    //

    return TypeOfOpen;
}
Exemple #20
0
NTSTATUS
Ext2TruncateIndirectFast(
    PEXT2_IRP_CONTEXT IrpContext,
    PEXT2_VCB         Vcb,
    PEXT2_MCB         Mcb
    )
{
    LONGLONG            Vba;
    LONGLONG            Lba;
    LONGLONG            Length;
    NTSTATUS            Status = STATUS_SUCCESS;
    int                 i;

    /* try to load all indirect blocks if mcb zone is not initialized */
    if (!IsZoneInited(Mcb)) {
        Status = Ext2InitializeZone(IrpContext, Vcb, Mcb);
        if (!NT_SUCCESS(Status)) {
            DbgBreak();
            ClearLongFlag(Mcb->Flags, MCB_ZONE_INITED);
            goto errorout;
        }
    }

    ASSERT (IsZoneInited(Mcb));

    /* delete all data blocks here */
    if (FsRtlNumberOfRunsInLargeMcb(&Mcb->Extents) != 0) {
        for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->Extents, i, &Vba, &Lba, &Length); i++) {
            /* ignore the non-existing runs */
            if (-1 == Lba || Vba == 0 || Length <= 0)
                continue;
            /* now do data block free */
            Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length);
        }
    }

    /* delete all meta blocks here */
    if (FsRtlNumberOfRunsInLargeMcb(&Mcb->MetaExts) != 0) {
        for (i = 0; FsRtlGetNextLargeMcbEntry(&Mcb->MetaExts, i, &Vba, &Lba, &Length); i++) {
            /* ignore the non-existing runs */
            if (-1 == Lba || Vba == 0 || Length <= 0)
                continue;
            /* now do meta block free */
            Ext2FreeBlock(IrpContext, Vcb, (ULONG)(Lba - 1), (ULONG)Length);
        }
    }

    /* clear data and meta extents */
    Ext2ClearAllExtents(&Mcb->Extents);
    Ext2ClearAllExtents(&Mcb->MetaExts);
    ClearFlag(Mcb->Flags, MCB_ZONE_INITED);

    /* clear inode blocks & sizes */
    Mcb->Inode.i_blocks = 0;
    Mcb->Inode.i_size = 0;
    memset(&Mcb->Inode.i_block[0], 0, sizeof(__u32) * 15);

    /* the caller will do inode save */

errorout:

    return Status;
}
Exemple #21
0
VOID
NtfsUpdateScbFromFileObject (
    IN PIRP_CONTEXT IrpContext,
    IN PFILE_OBJECT FileObject,
    IN PSCB Scb,
    IN BOOLEAN CheckTimeStamps
    )

/*++

Routine Description:

    This routine is called to update the Scb/Fcb to reflect the changes to
    a file through the fast io path.  It only called with a file object which
    represents a user's handle.

Arguments:

    FileObject - This is the file object used in the fast io path.

    Scb - This is the Scb for this stream.

    CheckTimeStamps - Indicates whether we want to update the time stamps from the
        fast io flags as well.  This will be TRUE if our caller will update the standard information,
        attribute header and duplicate info.  FALSE if only the attribute header and duplicate info.
        The latter case is the valid data length callback from the cache manager.

Return Value:

    None.

--*/

{

    PFCB Fcb = Scb->Fcb;
    ULONG CcbFlags;
    ULONG ScbFlags = 0;
    LONGLONG CurrentTime;

#if (__NDAS_NTFS_DBG__ && __NDAS_NTFS_SECONDARY__) 
	if (FlagOn(Fcb->NdasNtfsFlags, NDAS_NTFS_FCB_FLAG_SECONDARY))
		ASSERT( FALSE );
#endif

    //
    //  If the size of the main data stream is not part of the Fcb then update it
    //  now and set the correct Fcb flag.
    //

    if (FlagOn( Scb->ScbState, SCB_STATE_UNNAMED_DATA )) {

        if (Fcb->Info.FileSize != Scb->Header.FileSize.QuadPart) {

            Fcb->Info.FileSize = Scb->Header.FileSize.QuadPart;
            SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_FILE_SIZE );
        }

        if (Fcb->Info.AllocatedLength != Scb->TotalAllocated) {

            Fcb->Info.AllocatedLength = Scb->TotalAllocated;
            SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_ALLOC_SIZE );
        }

        if (FlagOn( FileObject->Flags, FO_FILE_SIZE_CHANGED )) {

            SetFlag( ScbFlags, SCB_STATE_CHECK_ATTRIBUTE_SIZE );
        }

    //
    //  Remember to update the size in the attribute header for named streams as well.
    //

    } else if (FlagOn( FileObject->Flags, FO_FILE_SIZE_CHANGED )) {

        SetFlag( ScbFlags, SCB_STATE_NOTIFY_RESIZE_STREAM | SCB_STATE_CHECK_ATTRIBUTE_SIZE );
    }

    ClearFlag( FileObject->Flags, FO_FILE_SIZE_CHANGED );

    //
    //  Check whether to update the time stamps if our caller requested it.
    //

    if (CheckTimeStamps && !FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE )) {

        BOOLEAN UpdateLastAccess = FALSE;
        BOOLEAN UpdateLastChange = FALSE;
        BOOLEAN UpdateLastModify = FALSE;
        BOOLEAN SetArchive = TRUE;

        //
        //  Copy the Ccb flags to a local variable.  Then we won't have to test
        //  for the existence of the Ccb each time.
        //

        CcbFlags = 0;

        //
        //  Capture the real flags if present and clear them since we will update the Scb/Fcb.
        //

        if (FileObject->FsContext2 != NULL) {

            CcbFlags = ((PCCB) FileObject->FsContext2)->Flags;
            ClearFlag( ((PCCB) FileObject->FsContext2)->Flags,
                       (CCB_FLAG_UPDATE_LAST_MODIFY |
                        CCB_FLAG_UPDATE_LAST_CHANGE |
                        CCB_FLAG_SET_ARCHIVE) );
        }

        NtfsGetCurrentTime( IrpContext, CurrentTime );

        //
        //  If there was a write to the file then update the last change, last access
        //  and last write and the archive bit.
        //

        if (FlagOn( FileObject->Flags, FO_FILE_MODIFIED )) {

            UpdateLastModify =
            UpdateLastAccess =
            UpdateLastChange = TRUE;

        //
        //  Otherwise test each of the individual bits in the file object and
        //  Ccb.
        //

        } else {

            if (FlagOn( FileObject->Flags, FO_FILE_FAST_IO_READ )) {

                UpdateLastAccess = TRUE;
            }

            if (FlagOn( CcbFlags, CCB_FLAG_UPDATE_LAST_CHANGE )) {

                UpdateLastChange = TRUE;

                if (FlagOn( CcbFlags, CCB_FLAG_UPDATE_LAST_MODIFY )) {

                    UpdateLastModify = TRUE;
                }

                if (!FlagOn( CcbFlags, CCB_FLAG_SET_ARCHIVE )) {

                    SetArchive = FALSE;
                }
            }
        }

        //
        //  Now set the correct Fcb bits.
        //

        if (UpdateLastChange) {

            if (SetArchive) {

                ASSERTMSG( "conflict with flush", 
                           ExIsResourceAcquiredSharedLite( Fcb->Resource ) || 
                           (Fcb->PagingIoResource != NULL && 
                            ExIsResourceAcquiredSharedLite( Fcb->PagingIoResource )));

                SetFlag( Fcb->Info.FileAttributes, FILE_ATTRIBUTE_ARCHIVE );
                SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_FILE_ATTR );
                SetFlag( Fcb->FcbState, FCB_STATE_UPDATE_STD_INFO );
            }

            if (!FlagOn( CcbFlags, CCB_FLAG_USER_SET_LAST_CHANGE_TIME )) {

                Fcb->Info.LastChangeTime = CurrentTime;
                SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_LAST_CHANGE );
                SetFlag( Fcb->FcbState, FCB_STATE_UPDATE_STD_INFO );
            }

            if (UpdateLastModify) {

                //
                //  Remember a change to a named data stream.
                //

                if (!FlagOn( Scb->ScbState, SCB_STATE_UNNAMED_DATA ) &&
                    (Scb->AttributeTypeCode == $DATA)) {

                    SetFlag( ScbFlags, SCB_STATE_NOTIFY_MODIFY_STREAM );
                }

                if (!FlagOn( CcbFlags, CCB_FLAG_USER_SET_LAST_MOD_TIME )) {

                    Fcb->Info.LastModificationTime = CurrentTime;
                    SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_LAST_MOD );
                    SetFlag( Fcb->FcbState, FCB_STATE_UPDATE_STD_INFO );
                }
            }
        }

        if (UpdateLastAccess &&
            !FlagOn( CcbFlags, CCB_FLAG_USER_SET_LAST_ACCESS_TIME ) &&
            !FlagOn( NtfsData.Flags, NTFS_FLAGS_DISABLE_LAST_ACCESS )) {

            Fcb->CurrentLastAccess = CurrentTime;
            SetFlag( Fcb->InfoFlags, FCB_INFO_UPDATE_LAST_ACCESS );
        }

        //
        //  Clear all of the fast io flags in the file object.
        //

        ClearFlag( FileObject->Flags, FO_FILE_MODIFIED | FO_FILE_FAST_IO_READ );
    }

    //
    //  Now store the Scb flags into the Scb.
    //

    if (ScbFlags) {

        NtfsAcquireFsrtlHeader( Scb );
        SetFlag( Scb->ScbState, ScbFlags );
        NtfsReleaseFsrtlHeader( Scb );
    }

    return;
}
Exemple #22
0
NTSTATUS
Ext2ExpandLast(
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb,
    IN PEXT2_MCB            Mcb,
    IN ULONG                Base,
    IN ULONG                Layer,
    IN PULONG *             Data,
    IN PULONG               Hint,
    IN PULONG               Block,
    IN OUT PULONG           Number
)
{
    PULONG      pData = NULL;
    ULONG       i;
    NTSTATUS    Status = STATUS_SUCCESS;

    if (Layer > 0 || IsMcbDirectory(Mcb)) {

        /* allocate buffer for new block */
        pData = (ULONG *) Ext2AllocatePool(
                    PagedPool,
                    BLOCK_SIZE,
                    EXT2_DATA_MAGIC
                );
        if (!pData) {
            DEBUG(DL_ERR, ( "Ex2ExpandBlock: failed to allocate memory for Data.\n"));
            Status = STATUS_INSUFFICIENT_RESOURCES;
            goto errorout;
        }
        RtlZeroMemory(pData, BLOCK_SIZE);
        INC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE);
    }

    /* allocate block from disk */
    Status = Ext2NewBlock(
                 IrpContext,
                 Vcb,
                 (Mcb->Inode.i_ino - 1) / BLOCKS_PER_GROUP,
                 *Hint,
                 Block,
                 Number
             );

    if (!NT_SUCCESS(Status)) {
        goto errorout;
    }

    /* increase inode i_blocks */
    Mcb->Inode.i_blocks += (*Number << (BLOCK_BITS - 9));

    if (Layer == 0) {

        if (IsMcbDirectory(Mcb)) {
            /* for directory we need initialize it's entry structure */
            PEXT2_DIR_ENTRY2 pEntry;
            pEntry = (PEXT2_DIR_ENTRY2) pData;
            pEntry->rec_len = (USHORT)(BLOCK_SIZE);
            ASSERT(*Number == 1);
            Ext2SaveBlock(IrpContext, Vcb, *Block, (PVOID)pData);
        }

        /* add new Extent into Mcb */
        if (!Ext2AddBlockExtent(Vcb, Mcb, Base, (*Block), *Number)) {
            DbgBreak();
            ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
            Ext2ClearAllExtents(&Mcb->Extents);
        }

    } else {

        /* zero the content of all meta blocks */
        for (i = 0; i < *Number; i++) {
            Ext2SaveBlock(IrpContext, Vcb, *Block + i, (PVOID)pData);
            /* add block to meta extents */
            if (!Ext2AddMcbMetaExts(Vcb, Mcb, *Block + i, 1)) {
                DbgBreak();
                Ext2Sleep(500);
                Ext2AddMcbMetaExts(Vcb, Mcb, *Block + i, 1);
            }
        }
    }

errorout:

    if (NT_SUCCESS(Status)) {
        *Hint = *Block + *Number;
        if (Data) {
            *Data = pData;
            ASSERT(*Number == 1);
        } else {
            if (pData) {
                Ext2FreePool(pData, EXT2_DATA_MAGIC);
                DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE);
            }
        }
    } else {
        if (pData) {
            Ext2FreePool(pData, EXT2_DATA_MAGIC);
            DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE);
        }
        if (*Block) {
            Ext2FreeBlock(IrpContext, Vcb, *Block, *Number);
            Mcb->Inode.i_blocks -= (*Number << (BLOCK_BITS - 9));
            *Block = 0;
        }
    }

    return Status;
}
Exemple #23
0
BOOLEAN
RtlAccessCheckEx(
    IN PSECURITY_DESCRIPTOR_ABSOLUTE SecurityDescriptor,
    IN PACCESS_TOKEN AccessToken,
    IN ACCESS_MASK DesiredAccess,
    IN ACCESS_MASK PreviouslyGrantedAccess,
    IN PGENERIC_MAPPING GenericMapping,
    OUT PACCESS_MASK RemainingDesiredAccess,
    OUT PACCESS_MASK GrantedAccess,
    OUT PNTSTATUS AccessStatus
    )
{
    NTSTATUS status = STATUS_ACCESS_DENIED;
    BOOLEAN isLocked = FALSE;
    ACCESS_MASK grantedAccess = PreviouslyGrantedAccess;
    ACCESS_MASK deniedAccess = 0;
    ACCESS_MASK desiredAccess = DesiredAccess;
    BOOLEAN wantMaxAllowed = FALSE;
    USHORT aclSizeUsed = 0;
    USHORT aceOffset = 0;
    PACE_HEADER aceHeader = NULL;
    union {
        SID Sid;
        BYTE Buffer[SID_MAX_SIZE];
    } sidBuffer;
    ULONG ulSidSize = sizeof(sidBuffer);

    if (!SecurityDescriptor || !AccessToken || !GenericMapping)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!LW_IS_VALID_FLAGS(DesiredAccess, VALID_DESIRED_ACCESS_MASK))
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!LW_IS_VALID_FLAGS(PreviouslyGrantedAccess, VALID_GRANTED_ACCESS_MASK))
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if ((SecurityDescriptor->Owner == NULL) || 
        (SecurityDescriptor->Group == NULL))
    {
        status = STATUS_INVALID_SECURITY_DESCR;
        GOTO_CLEANUP();
    }

    wantMaxAllowed = IsSetFlag(desiredAccess, MAXIMUM_ALLOWED);
    ClearFlag(desiredAccess, MAXIMUM_ALLOWED);

    RtlMapGenericMask(&desiredAccess, GenericMapping);

    //
    // NT AUTHORITY\SYSTEM is always allowed an access
    //
    status = RtlCreateWellKnownSid(WinLocalSystemSid,
                                   NULL,
                                   &sidBuffer.Sid,
                                   &ulSidSize);
    GOTO_CLEANUP_ON_STATUS(status);

    SHARED_LOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid))
    {
        if (wantMaxAllowed)
        {
            SetFlag(desiredAccess, STANDARD_RIGHTS_ALL);
            SetFlag(desiredAccess, GENERIC_ALL);
            RtlMapGenericMask(&desiredAccess, GenericMapping);
        }
        SetFlag(grantedAccess, desiredAccess);
        desiredAccess = 0;

        status = STATUS_SUCCESS;
        GOTO_CLEANUP();
    }

    if (wantMaxAllowed || IsSetFlag(desiredAccess, ACCESS_SYSTEM_SECURITY))
    {
        // TODO-Handle ACCESS_SYSTEM_SECURITY by checking SE_SECURITY_NAME
        // privilege.  For now, requesting ACCESS_SYSTEM_SECURITY is not
        // allowed.

        ulSidSize = sizeof(sidBuffer);
        status = RtlCreateWellKnownSid(
                     WinBuiltinAdministratorsSid,
                     NULL,
                     &sidBuffer.Sid,
                     &ulSidSize);
        GOTO_CLEANUP_ON_STATUS(status);

        if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid))
        {
            SetFlag(grantedAccess, ACCESS_SYSTEM_SECURITY);
            ClearFlag(desiredAccess, ACCESS_SYSTEM_SECURITY);
        }
        else if (IsSetFlag(desiredAccess, ACCESS_SYSTEM_SECURITY))
        {
            status = STATUS_PRIVILEGE_NOT_HELD;
            GOTO_CLEANUP();
        }
    }

    if (wantMaxAllowed || IsSetFlag(desiredAccess, WRITE_OWNER))
    {
        // TODO-Allow WRITE_OWNER if have SE_TAKE_OWNERSHIP_NAME regardless
        // of DACL.

        //
        // BUILTIN\Administrators are always allowed WRITE_OWNER
        //

        ulSidSize = sizeof(sidBuffer);
        status = RtlCreateWellKnownSid(
                     WinBuiltinAdministratorsSid,
                     NULL,
                     &sidBuffer.Sid,
                     &ulSidSize);
        GOTO_CLEANUP_ON_STATUS(status);

        if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid))
        {
            SetFlag(grantedAccess, WRITE_OWNER);
            ClearFlag(desiredAccess, WRITE_OWNER);
        }
    }

    //
    // Owner can always read the SD and write the DACL.
    //

    if (wantMaxAllowed || IsSetFlag(desiredAccess, READ_CONTROL | WRITE_DAC))
    {
        if (RtlIsSidMemberOfToken(AccessToken, SecurityDescriptor->Owner))
        {
            if (wantMaxAllowed)
            {
                desiredAccess |= (READ_CONTROL | WRITE_DAC);
            }
                
            SetFlag(grantedAccess, (READ_CONTROL | WRITE_DAC) & desiredAccess);
            ClearFlag(desiredAccess, grantedAccess);
        }
    }

    // TODO-MAXIMUM_ALLOWED wrt privileges and WRITE_OWNER and
    // ACCESS_SYSTEM_SECURITY above.

    if (!SecurityDescriptor->Dacl)
    {
        // TODO-Interplay with special bits above?
        if (wantMaxAllowed)
        {
            SetFlag(desiredAccess, STANDARD_RIGHTS_ALL);
            SetFlag(desiredAccess, GENERIC_ALL);
            RtlMapGenericMask(&desiredAccess, GenericMapping);
        }
        SetFlag(grantedAccess, desiredAccess);
        desiredAccess = 0;

        status = STATUS_SUCCESS;
        GOTO_CLEANUP();
    }

    if (!RtlValidAcl(SecurityDescriptor->Dacl, &aclSizeUsed))
    {
        status = STATUS_INVALID_ACL;
        GOTO_CLEANUP();
    }

    while (wantMaxAllowed || desiredAccess)
    {
        status = RtlIterateAce(SecurityDescriptor->Dacl,
                               aclSizeUsed,
                               &aceOffset,
                               &aceHeader);
        if (STATUS_NO_MORE_ENTRIES == status)
        {
            break;
        }
        GOTO_CLEANUP_ON_STATUS(status);

        // Check ACE
        switch (aceHeader->AceType)
        {
            case ACCESS_ALLOWED_ACE_TYPE:
            {
                PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE) aceHeader;
                ACCESS_MASK mask = ace->Mask;

                RtlMapGenericMask(&mask, GenericMapping);

                if (wantMaxAllowed || IsSetFlag(desiredAccess, mask))
                {
                    // SID in token => add bits to granted bits
                    PSID sid = RtlpGetSidAccessAllowedAce(ace);

                    if (RtlIsSidMemberOfToken(AccessToken, sid))
                    {
                        if (wantMaxAllowed)
                        {
                            SetFlag(grantedAccess, mask & ~deniedAccess);
                        }
                        else
                        {
                            SetFlag(grantedAccess, mask & desiredAccess);
                        }

                        ClearFlag(desiredAccess, grantedAccess);
                    }
                }
                break;
            }
            case ACCESS_DENIED_ACE_TYPE:
            {
                // Allowed and deny ACEs are isomorphic.
                PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE) aceHeader;
                ACCESS_MASK mask = ace->Mask;

                RtlMapGenericMask(&mask, GenericMapping);

                if (wantMaxAllowed || IsSetFlag(desiredAccess, mask))
                {
                    // SID in token => exit with STATUS_ACCESS_DENIED
                    PSID sid = RtlpGetSidAccessAllowedAce(ace);

                    if (RtlIsSidMemberOfToken(AccessToken, sid))
                    {
                        if (wantMaxAllowed)
                        {
                            SetFlag(deniedAccess, mask);
                        }
                        else
                        {
                            status = STATUS_ACCESS_DENIED;
                            GOTO_CLEANUP();
                        }

                        ClearFlag(desiredAccess, deniedAccess);
                    }
                }
                break;
            }
            default:
                // ignore
                break;
        }
    }

    status = desiredAccess ? STATUS_ACCESS_DENIED : STATUS_SUCCESS;

cleanup:
    UNLOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (NT_SUCCESS(status) &&
        !LW_IS_VALID_FLAGS(grantedAccess, VALID_GRANTED_ACCESS_MASK))
    {
        status = STATUS_ASSERTION_FAILURE;
    }
    if (!NT_SUCCESS(status))
    {
        grantedAccess = PreviouslyGrantedAccess;
    }

    if (RemainingDesiredAccess)
    {
        *RemainingDesiredAccess = desiredAccess;
    }

    *GrantedAccess = grantedAccess;
    *AccessStatus = status;

    return NT_SUCCESS(status) ? TRUE : FALSE;
}
Exemple #24
0
NTSTATUS
Ext2ExpandBlock(
    IN PEXT2_IRP_CONTEXT IrpContext,
    IN PEXT2_VCB         Vcb,
    IN PEXT2_MCB         Mcb,
    IN ULONG             Base,
    IN ULONG             Layer,
    IN ULONG             Start,
    IN ULONG             SizeArray,
    IN PULONG            BlockArray,
    IN PULONG            Hint,
    IN PULONG            Extra
)
{
    ULONG       i = 0;
    ULONG       j;
    ULONG       Slot;
    ULONG       Block = 0;
    LARGE_INTEGER Offset;

    PBCB        Bcb = NULL;
    PULONG      pData = NULL;
    ULONG       Skip = 0;

    ULONG       Number;
    ULONG       Wanted;

    NTSTATUS    Status = STATUS_SUCCESS;

    if (Layer == 1) {

        /*
         * try to make all leaf block continuous to avoid fragments
         */

        Number = min(SizeArray, ((*Extra + (Start & (BLOCK_SIZE/4 - 1))) * 4 / BLOCK_SIZE));
        Wanted = 0;
        DEBUG(DL_BLK, ("Ext2ExpandBlock: SizeArray=%xh Extra=%xh Start=%xh %xh\n",
                       SizeArray, *Extra, Start, Number ));

        for (i=0; i < Number; i++) {
            if (BlockArray[i] == 0) {
                Wanted += 1;
            }
        }

        i = 0;
        while (Wanted > 0) {

            Number = Wanted;
            Status = Ext2ExpandLast(
                         IrpContext,
                         Vcb,
                         Mcb,
                         Base,
                         Layer,
                         NULL,
                         Hint,
                         &Block,
                         &Number
                     );
            if (!NT_SUCCESS(Status)) {
                goto errorout;
            }

            ASSERT(Number > 0);
            Wanted -= Number;
            while (Number) {
                if (BlockArray[i] == 0) {
                    BlockArray[i] = Block++;
                    Number--;
                }
                i++;
            }
        }

    } else if (Layer == 0) {

        /*
         * bulk allocation for inode data blocks
         */

        i = 0;

        while (*Extra && i < SizeArray) {

            Wanted = 0;
            Number = 1;

            for (j = i; j < SizeArray && j < i + *Extra; j++) {

                if (BlockArray[j] >= TOTAL_BLOCKS) {
                    DbgBreak();
                    BlockArray[j] = 0;
                }

                if (BlockArray[j] == 0) {
                    Wanted += 1;
                } else {
                    break;
                }
            }

            if (Wanted == 0) {

                /* add block extent into Mcb */
                ASSERT(BlockArray[i] != 0);
                if (!Ext2AddBlockExtent(Vcb, Mcb, Base + i, BlockArray[i], 1)) {
                    DbgBreak();
                    ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
                    Ext2ClearAllExtents(&Mcb->Extents);
                }

            } else {

                Number = Wanted;
                Status = Ext2ExpandLast(
                             IrpContext,
                             Vcb,
                             Mcb,
                             Base + i,
                             0,
                             NULL,
                             Hint,
                             &Block,
                             &Number
                         );
                if (!NT_SUCCESS(Status)) {
                    goto errorout;
                }

                ASSERT(Number > 0);
                for (j = 0; j < Number; j++) {
                    BlockArray[i + j] = Block++;
                }
            }

            *Extra -= Number;
            i += Number;
        }

        goto errorout;
    }


    /*
     * only for meta blocks allocation
     */

    for (i = 0; *Extra && i < SizeArray; i++) {

        if (Layer <= 3) {

            if (BlockArray[i] >= TOTAL_BLOCKS) {
                DbgBreak();
                BlockArray[i] = 0;
            }

            if (BlockArray[i] == 0) {
                Number = 1;
                Status = Ext2ExpandLast(
                             IrpContext,
                             Vcb,
                             Mcb,
                             Base,
                             Layer,
                             &pData,
                             Hint,
                             &BlockArray[i],
                             &Number
                         );
                if (!NT_SUCCESS(Status)) {
                    goto errorout;
                }

            } else {

                Offset.QuadPart = (((LONGLONG)BlockArray[i]) << BLOCK_BITS);
                if (!CcPinRead(
                            Vcb->Volume,
                            &Offset,
                            BLOCK_SIZE,
                            PIN_WAIT,
                            &Bcb,
                            (void **)&pData )) {

                    DEBUG(DL_ERR, ( "Ext2ExpandInode: failed to PinLock offset :%I64xh...\n",
                                    Offset.QuadPart));
                    Status = STATUS_CANT_WAIT;
                    DbgBreak();
                    goto errorout;
                }

                /* add block to meta extents */
                if (!Ext2AddMcbMetaExts(Vcb, Mcb,  BlockArray[i], 1)) {
                    DbgBreak();
                    Ext2Sleep(500);
                    Ext2AddMcbMetaExts(Vcb, Mcb,  BlockArray[i], 1);
                }
            }

            Skip = Vcb->max_blocks_per_layer[Layer] * i;

            if (i == 0) {
                if (Layer > 1) {
                    Slot  = Start / Vcb->max_blocks_per_layer[Layer - 1];
                    Start = Start % Vcb->max_blocks_per_layer[Layer - 1];
                    Skip += Slot * Vcb->max_blocks_per_layer[Layer - 1];
                } else {
                    Slot  = Start;
                    Start = 0;
                    Skip += Slot;
                }
            } else {
                Start = 0;
                Slot  = 0;
            }

            Status = Ext2ExpandBlock(
                         IrpContext,
                         Vcb,
                         Mcb,
                         Base + Skip,
                         Layer - 1,
                         Start,
                         BLOCK_SIZE/4 - Slot,
                         &pData[Slot],
                         Hint,
                         Extra
                     );

            if (Bcb) {
                CcSetDirtyPinnedData(Bcb, NULL);
                if (!Ext2AddBlockExtent(Vcb, NULL,
                                        BlockArray[i],
                                        BlockArray[i], 1)) {
                    DbgBreak();
                    Ext2Sleep(500);
                    if (!Ext2AddBlockExtent(Vcb, NULL,
                                            BlockArray[i],
                                            BlockArray[i], 1)) {
                    }
                }
            } else {
                Ext2SaveBlock(IrpContext, Vcb, BlockArray[i], (PVOID)pData);
            }

            if (pData) {
                if (Bcb) {
                    CcUnpinData(Bcb);
                    Bcb = NULL;
                } else {
                    Ext2FreePool(pData, EXT2_DATA_MAGIC);
                    DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE);
                }
                pData = NULL;
            }

            if (!NT_SUCCESS(Status)) {
                DbgBreak();
                break;
            }
        }
    }

errorout:

    return Status;
}
PRInt32 nsMailboxProtocol::ReadMessageResponse(nsIInputStream * inputStream, PRUint32 sourceOffset, PRUint32 length)
{
  char *line = nsnull;
  PRUint32 status = 0;
  nsresult rv = NS_OK;
  mCurrentProgress += length;
  
  // if we are doing a move or a copy, forward the data onto the copy handler...
  // if we want to display the message then parse the incoming data...
  
  if (m_channelListener)
  {
    // just forward the data we read in to the listener...
    rv = m_channelListener->OnDataAvailable(this, m_channelContext, inputStream, sourceOffset, length);
  }
  else
  {
    PRBool pauseForMoreData = PR_FALSE;
    PRBool canonicalLineEnding = PR_FALSE;
    nsCOMPtr<nsIMsgMessageUrl> msgurl = do_QueryInterface(m_runningUrl);
    
    if (msgurl)
      msgurl->GetCanonicalLineEnding(&canonicalLineEnding);
    do
    {
      char *saveLine;
      saveLine = line = m_lineStreamBuffer->ReadNextLine(inputStream, status, pauseForMoreData);
      
      if (!line || (line[0] == '.' && line[1] == 0))
      {
        // we reached the end of the message!
        ClearFlag(MAILBOX_PAUSE_FOR_READ);
      } // otherwise process the line
      else
      {
        if (line[0] == '.')
          line++; // skip over the '.'
        
        /* When we're sending this line to a converter (ie,
        it's a message/rfc822) use the local line termination
        convention, not CRLF.  This makes text articles get
        saved with the local line terminators.  Since SMTP
        and NNTP mandate the use of CRLF, it is expected that
        the local system will convert that to the local line
        terminator as it is read.
        */
        // mscott - the firstline hack is aimed at making sure we don't write
        // out the dummy header when we are trying to display the message.
        // The dummy header is the From line with the date tag on it.
        if (m_msgFileOutputStream && TestFlag(MAILBOX_MSG_PARSE_FIRST_LINE))
        {
          PRUint32 count = 0;
          if (line)
            rv = m_msgFileOutputStream->Write(line, PL_strlen(line),
            &count);
          if (NS_FAILED(rv)) break;
          
          if (canonicalLineEnding)
            rv = m_msgFileOutputStream->Write(CRLF, 2, &count);
          else
            rv = m_msgFileOutputStream->Write(MSG_LINEBREAK,
            MSG_LINEBREAK_LEN, &count);
          
          if (NS_FAILED(rv)) break;
        }
        else
          SetFlag(MAILBOX_MSG_PARSE_FIRST_LINE);
      } 
      PR_Free(saveLine);
    }
    while (line && !pauseForMoreData);
  }
  
  SetFlag(MAILBOX_PAUSE_FOR_READ); // wait for more data to become available...
  if (mProgressEventSink)
  {
    PRInt32 contentLength = 0;
    GetContentLength(&contentLength);
    // XXX 64-bit
    mProgressEventSink->OnProgress(this, m_channelContext,
                                   nsUint64(mCurrentProgress),
                                   nsUint64(contentLength));
  }
  
  if (NS_FAILED(rv)) return -1;
  
  return 0;
}
Exemple #26
0
NTSTATUS
Ext2TruncateBlock(
    IN PEXT2_IRP_CONTEXT IrpContext,
    IN PEXT2_VCB         Vcb,
    IN PEXT2_MCB         Mcb,
    IN ULONG             Base,
    IN ULONG             Start,
    IN ULONG             Layer,
    IN ULONG             SizeArray,
    IN PULONG            BlockArray,
    IN PULONG            Extra
)
{
    NTSTATUS    Status = STATUS_SUCCESS;
    ULONG       i = 0;
    ULONG       Slot = 0;
    ULONG       Skip = 0;

    LONGLONG    Offset;
    PBCB        Bcb = NULL;
    PULONG      pData = NULL;

    ASSERT(Mcb != NULL);

    for (i = 0; i < SizeArray; i++) {

        if (Layer == 0) {

            ULONG   Number = 1;

            while (Extra &&  SizeArray > i + 1 && Number < *Extra) {

                if (BlockArray[SizeArray - i - 1] ==
                    BlockArray[SizeArray - i - 2] + 1) {

                    BlockArray[SizeArray - i - 1] = 0;
                    Number++;
                    SizeArray--;

                } else {
                    break;
                }
            }

            if (BlockArray[SizeArray - i - 1]) {

                Status = Ext2FreeBlock(IrpContext, Vcb, BlockArray[SizeArray - i - 1], Number);
                if (NT_SUCCESS(Status)) {
                    ASSERT(Mcb->Inode.i_blocks >= (Number << (BLOCK_BITS - 9)));
                    if (Mcb->Inode.i_blocks < (Number << (BLOCK_BITS - 9))) {
                        Mcb->Inode.i_blocks = 0;
                        DbgBreak();
                    } else {
                        Mcb->Inode.i_blocks -= (Number << (BLOCK_BITS - 9));
                    }
                    BlockArray[SizeArray - i - 1] = 0;
                }
            }

            if (Extra) {

                /* dec blocks count */
                ASSERT(*Extra >= Number);
                *Extra = *Extra - Number;

                /* remove block mapping frm Mcb Extents */
                if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + SizeArray - 1 - i, Number)) {
                    DbgBreak();
                    ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
                    Ext2ClearAllExtents(&Mcb->Extents);
                }
            }

        } else {

            ASSERT(Layer <= 3);

            if (BlockArray[SizeArray - i - 1] >= TOTAL_BLOCKS) {
                DbgBreak();
                BlockArray[SizeArray - i - 1] = 0;
            }

            if (i == 0) {
                if (Layer > 1) {
                    Slot  = Start / Vcb->max_blocks_per_layer[Layer - 1];
                    Start = Start % Vcb->max_blocks_per_layer[Layer - 1];
                } else {
                    Slot  = Start;
                    Start = (BLOCK_SIZE / 4) - 1;
                }
            } else {
                Slot = Start = (BLOCK_SIZE / 4) - 1;
            }

            Skip = (SizeArray - i - 1) * Vcb->max_blocks_per_layer[Layer];

            if (BlockArray[SizeArray - i - 1]) {

                Offset = (LONGLONG) (BlockArray[SizeArray - i - 1]);
                Offset = Offset << BLOCK_BITS;

                if (!CcPinRead( Vcb->Volume,
                                (PLARGE_INTEGER) (&Offset),
                                BLOCK_SIZE,
                                PIN_WAIT,
                                &Bcb,
                                (void **)&pData )) {

                    DEBUG(DL_ERR, ( "Ext2TruncateBlock: PinLock failed on block %xh ...\n",
                                    BlockArray[SizeArray - i - 1]));
                    Status = STATUS_CANT_WAIT;
                    DbgBreak();
                    goto errorout;
                }

                Status = Ext2TruncateBlock(
                             IrpContext,
                             Vcb,
                             Mcb,
                             Base + Skip,
                             Start,
                             Layer - 1,
                             Slot + 1,
                             &pData[0],
                             Extra
                         );

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

                CcSetDirtyPinnedData(Bcb, NULL);
                Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)BLOCK_SIZE);

                if (*Extra || Ext2IsBlockEmpty(pData, BLOCK_SIZE/4)) {

                    Ext2TruncateBlock(
                                 IrpContext,
                                 Vcb,
                                 Mcb,
                                 Base + Skip,    /* base */
                                 0,              /* start */
                                 0,              /* layer */
                                 1,
                                 &BlockArray[SizeArray - i - 1],
                                 NULL
                             );

                    if (!Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1)) {
                        DbgBreak();
                        Ext2Sleep(500);
                        Ext2RemoveMcbMetaExts(Vcb, Mcb, BlockArray[SizeArray - i - 1], 1);
                    }
                }

                if (pData) {
                    CcUnpinData(Bcb);
                    Bcb = NULL;
                    pData = NULL;
                }

            } else {

                if (Layer > 1) {
                    if (*Extra > Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1) {
                        *Extra -= (Slot * Vcb->max_blocks_per_layer[Layer - 1] + Start + 1);
                    } else {
                        *Extra  = 0;
                    }
                } else {
                    if (*Extra > Slot + 1) {
                        *Extra -= (Slot + 1);
                    } else {
                        *Extra  = 0;
                    }
                }

                if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + Skip, (Start + 1))) {
                    DbgBreak();
                    ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
                    Ext2ClearAllExtents(&Mcb->Extents);
                }
            }
        }

        if (Extra && *Extra == 0) {
            break;
        }
    }

errorout:

    if (pData) {
        CcUnpinData(Bcb);
    }

    return Status;
}
Exemple #27
0
VOID
FatRemoveNames (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine will remove the short name and any long names associated
    with the files from their repsective splay tree.

Arguments:

    Name - Supplies the Fcb to process.

Return Value:

    None.

--*/

{
    PDCB Parent;
    PRTL_SPLAY_LINKS NewRoot;

    PAGED_CODE();
    UNREFERENCED_PARAMETER( IrpContext );
    
    Parent = Fcb->ParentDcb;

    //
    //  We used to assert this condition, but it really isn't good.  If
    //  someone rapidly renames a directory multiple times and we can't
    //  flush the lower fcbs fast enough (that didn't go away synch.)
    //  well, well hit some of them again.
    //
    //  NT_ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_NAMES_IN_SPLAY_TREE ));
    //

    if (FlagOn( Fcb->FcbState, FCB_STATE_NAMES_IN_SPLAY_TREE )) {

        //
        //  Delete the node short name.
        //

        NewRoot = RtlDelete(&Fcb->ShortName.Links);

        Parent->Specific.Dcb.RootOemNode = NewRoot;

        //
        //  Now check for the presence of long name and delete it.
        //

        if (FlagOn( Fcb->FcbState, FCB_STATE_HAS_OEM_LONG_NAME )) {

            NewRoot = RtlDelete(&Fcb->LongName.Oem.Links);

            Parent->Specific.Dcb.RootOemNode = NewRoot;

            RtlFreeOemString( &Fcb->LongName.Oem.Name.Oem );

            ClearFlag( Fcb->FcbState, FCB_STATE_HAS_OEM_LONG_NAME );
        }

        if (FlagOn( Fcb->FcbState, FCB_STATE_HAS_UNICODE_LONG_NAME )) {

            NewRoot = RtlDelete(&Fcb->LongName.Unicode.Links);

            Parent->Specific.Dcb.RootUnicodeNode = NewRoot;

            RtlFreeUnicodeString( &Fcb->LongName.Unicode.Name.Unicode );

            ClearFlag( Fcb->FcbState, FCB_STATE_HAS_UNICODE_LONG_NAME );
        }

        ClearFlag( Fcb->FcbState, FCB_STATE_NAMES_IN_SPLAY_TREE );
    }

    return;
}
Exemple #28
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;
}