Exemplo n.º 1
0
VOID
PacketFree(
    IN PNDIS_PACKET	Packet
)
{
    PLPX_RESERVED	reserved = RESERVED(Packet);
    PUCHAR			packetData;
    PNDIS_BUFFER	pNdisBuffer;
    UINT			uiLength;
    LONG			clone ;

    DebugPrint(3, ("PacketFree reserved->type = %d\n", reserved->Type));

    switch(reserved->Type) {

    case SEND_TYPE:

        clone = InterlockedDecrement(&reserved->Cloned);
        if(clone >= 0) {
            return;
        }

        pNdisBuffer = NULL;
        NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        if(pNdisBuffer) {

            NdisQueryBufferSafe(
                pNdisBuffer,
                &packetData,
                &uiLength,
                HighPagePriority
            );

            NdisFreeMemory(packetData);
            NdisFreeBuffer(pNdisBuffer);
        }
        pNdisBuffer = NULL;
        NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        while(pNdisBuffer) {
            NdisFreeBuffer(pNdisBuffer);
            pNdisBuffer = NULL;
            NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        }
        if(reserved->IrpSp != NULL) {
            LpxDereferenceSendIrp(reserved->IrpSp);
        } else {
            DebugPrint(2, ("[LPX] PacketFree: No IrpSp\n")) ;
        }
        break;

    case RECEIVE_TYPE:

        if(reserved->LpxSmpHeader)
            //ExFreePool(reserved->LpxSmpHeader);
            NdisFreeMemory(reserved->LpxSmpHeader);

        pNdisBuffer = NULL;
        NdisUnchainBufferAtFront(Packet, &pNdisBuffer);
        if(pNdisBuffer) {
            NdisQueryBufferSafe(
                pNdisBuffer,
                &packetData,
                &uiLength,
                HighPagePriority
            );

            NdisFreeMemory(packetData);
            NdisFreeBuffer(pNdisBuffer);
        }
        reserved->PacketDataOffset = 0;

        break;

    }

    NdisFreePacket(Packet);

    InterlockedDecrement(&NumberOfPackets);

    DebugPrint(2, ("Packet REALLY Freed Numberofpackets = %d\n", NumberOfPackets));
}
Exemplo n.º 2
0
long juce_InterlockedDecrement (volatile long* a) noexcept                       { return InterlockedDecrement (a); }
Exemplo n.º 3
0
int TestInterlockedAccess(int argc, char* argv[])
{
	int index;
	LONG* Addend;
	LONG* Target;
	LONG oldValue;
	LONG* Destination;
	LONGLONG oldValue64;
	LONGLONG* Destination64;

	/* InterlockedIncrement */

	Addend = _aligned_malloc(sizeof(LONG), sizeof(LONG));
	if (!Addend)
	{
		printf("Failed to allocate memory\n");
		return -1;
	}

	*Addend = 0;

	for (index = 0; index < 10; index ++)
		InterlockedIncrement(Addend);

	if (*Addend != 10)
	{
		printf("InterlockedIncrement failure: Actual: %"PRId32", Expected: 10\n", *Addend);
		return -1;
	}

	/* InterlockedDecrement */

	for (index = 0; index < 10; index ++)
		InterlockedDecrement(Addend);

	if (*Addend != 0)
	{
		printf("InterlockedDecrement failure: Actual: %"PRId32", Expected: 0\n", *Addend);
		return -1;
	}

	/* InterlockedExchange */

	Target = _aligned_malloc(sizeof(LONG), sizeof(LONG));

	if (!Target)
	{
		printf("Failed to allocate memory\n");
		return -1;
	}

	*Target = 0xAA;

	oldValue = InterlockedExchange(Target, 0xFF);

	if (oldValue != 0xAA)
	{
		printf("InterlockedExchange failure: Actual: 0x%08"PRIX32", Expected: 0xAA\n", oldValue);
		return -1;
	}

	if (*Target != 0xFF)
	{
		printf("InterlockedExchange failure: Actual: 0x%08"PRIX32", Expected: 0xFF\n", *Target);
		return -1;
	}

	/* InterlockedExchangeAdd */

	*Addend = 25;

	oldValue = InterlockedExchangeAdd(Addend, 100);

	if (oldValue != 25)
	{
		printf("InterlockedExchangeAdd failure: Actual: %"PRId32", Expected: 25\n", oldValue);
		return -1;
	}

	if (*Addend != 125)
	{
		printf("InterlockedExchangeAdd failure: Actual: %"PRId32", Expected: 125\n", *Addend);
		return -1;
	}

	/* InterlockedCompareExchange (*Destination == Comparand) */

	Destination = _aligned_malloc(sizeof(LONG), sizeof(LONG));
	if (!Destination)
	{
		printf("Failed to allocate memory\n");
		return -1;
	}

	*Destination = 0xAABBCCDD;

	oldValue = InterlockedCompareExchange(Destination, 0xCCDDEEFF, 0xAABBCCDD);

	if (oldValue != 0xAABBCCDD)
	{
		printf("InterlockedCompareExchange failure: Actual: 0x%08"PRIX32", Expected: 0xAABBCCDD\n", oldValue);
		return -1;
	}

	if (*Destination != 0xCCDDEEFF)
	{
		printf("InterlockedCompareExchange failure: Actual: 0x%08"PRIX32", Expected: 0xCCDDEEFF\n", *Destination);
		return -1;
	}

	/* InterlockedCompareExchange (*Destination != Comparand) */

	*Destination = 0xAABBCCDD;

	oldValue = InterlockedCompareExchange(Destination, 0xCCDDEEFF, 0x66778899);

	if (oldValue != 0xAABBCCDD)
	{
		printf("InterlockedCompareExchange failure: Actual: 0x%08"PRIX32", Expected: 0xAABBCCDD\n", oldValue);
		return -1;
	}

	if (*Destination != 0xAABBCCDD)
	{
		printf("InterlockedCompareExchange failure: Actual: 0x%08"PRIX32", Expected: 0xAABBCCDD\n", *Destination);
		return -1;
	}

	/* InterlockedCompareExchange64 (*Destination == Comparand) */

	Destination64 = _aligned_malloc(sizeof(LONGLONG), sizeof(LONGLONG));
	if (!Destination64)
	{
		printf("Failed to allocate memory\n");
		return -1;
	}

	*Destination64 = 0x66778899AABBCCDD;

	oldValue64 = InterlockedCompareExchange64(Destination64, 0x8899AABBCCDDEEFF, 0x66778899AABBCCDD);

	if (oldValue64 != 0x66778899AABBCCDD)
	{
		printf("InterlockedCompareExchange failure: Actual: 0x%016"PRIX64", Expected: 0x66778899AABBCCDD\n", oldValue64);
		return -1;
	}

	if (*Destination64 != 0x8899AABBCCDDEEFF)
	{
		printf("InterlockedCompareExchange failure: Actual: 0x%016"PRIX64", Expected: 0x8899AABBCCDDEEFF\n", *Destination64);
		return -1;
	}

	/* InterlockedCompareExchange64 (*Destination != Comparand) */

	*Destination64 = 0x66778899AABBCCDD;

	oldValue64 = InterlockedCompareExchange64(Destination64, 0x8899AABBCCDDEEFF, 12345);

	if (oldValue64 != 0x66778899AABBCCDD)
	{
		printf("InterlockedCompareExchange failure: Actual: 0x%016"PRIX64", Expected: 0x66778899AABBCCDD\n", oldValue64);
		return -1;
	}

	if (*Destination64 != 0x66778899AABBCCDD)
	{
		printf("InterlockedCompareExchange failure: Actual: 0x%016"PRIX64", Expected: 0x66778899AABBCCDD\n", *Destination64);
		return -1;
	}

	_aligned_free(Addend);
	_aligned_free(Target);
	_aligned_free(Destination);
	_aligned_free(Destination64);

	return 0;
}
Exemplo n.º 4
0
static ULONG WINAPI CStdPSFactory_Release(LPPSFACTORYBUFFER iface)
{
  CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
  TRACE("(%p)->Release()\n",iface);
  return InterlockedDecrement( &This->RefCount );
}
Exemplo n.º 5
0
//
// Wait for registration message and forward proper arbiter.
//
VOID
DraidReceptionThreadProc(
	IN PVOID Param
) {
	PDRAID_REMOTE_CLIENT_CONNECTION Connection = Param;
	LARGE_INTEGER Timeout;
	NTSTATUS status;
	DRIX_REGISTER RegMsg;
	DRIX_HEADER Reply = {0};
	PDRAID_ARBITER_INFO Arbiter;
	KIRQL	oldIrql;
	PLIST_ENTRY listEntry;
	BOOLEAN Disconnect = TRUE;
	BOOLEAN MatchFound;
	ULONG		result;
	
	Connection->TdiReceiveContext.Irp = NULL;
	KeInitializeEvent(&Connection->TdiReceiveContext.CompletionEvent, NotificationEvent, FALSE) ;
	
	// Wait for network event or short timeout
	status = LpxTdiRecvWithCompletionEvent(
					Connection->ConnectionFileObject,
					&Connection->TdiReceiveContext,
					(PUCHAR)&RegMsg,
					sizeof(DRIX_REGISTER),
					0,
					NULL,
					NULL
					);
	if(!NT_SUCCESS(status)) {
		KDPrintM(DBG_LURN_INFO, ("LpxTdiRecvWithCompletionEvent returned %d.\n", status));
		goto out;
	}

	Timeout.QuadPart =  - HZ * 5;
	
	status = KeWaitForSingleObject(
		&Connection->TdiReceiveContext.CompletionEvent,
		Executive, KernelMode, 	FALSE, &Timeout);
	
	if (status == STATUS_SUCCESS) {
		UCHAR ResultCode;
		
		//
		// Data received. Check validity and forward channel to arbiter.
		//
		if (Connection->TdiReceiveContext.Result != sizeof(DRIX_REGISTER)) {
			KDPrintM(DBG_LURN_INFO, ("Registration packet size is not %d.\n", sizeof(DRIX_REGISTER)));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}

		if (NTOHL(RegMsg.Header.Signature) != DRIX_SIGNATURE) {
			KDPrintM(DBG_LURN_INFO, ("DRIX signature mismatch\n"));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}
		
		if (RegMsg.Header.Command != DRIX_CMD_REGISTER) {
			KDPrintM(DBG_LURN_INFO, ("Inappropriate command %x sent.\n", RegMsg.Header.Command));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}

		if (RegMsg.Header.ReplyFlag) {
			KDPrintM(DBG_LURN_INFO, ("Reply flag should be cleared\n"));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}
		if (NTOHS(RegMsg.Header.Length) !=  sizeof(DRIX_REGISTER)) {
			KDPrintM(DBG_LURN_INFO, ("Invalid packet length %d\n", NTOHS(RegMsg.Header.Length)));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}

		ACQUIRE_SPIN_LOCK(&g_DraidGlobals->ArbiterListSpinlock, &oldIrql);
		MatchFound = FALSE;
		for (listEntry = g_DraidGlobals->ArbiterList.Flink;
			listEntry != &g_DraidGlobals->ArbiterList;
			listEntry = listEntry->Flink) 
		{
			Arbiter = CONTAINING_RECORD (listEntry, DRAID_ARBITER_INFO, AllArbiterList);
			if (RtlCompareMemory(&Arbiter->Rmd.RaidSetId, &RegMsg.RaidSetId, sizeof(GUID)) == sizeof(GUID) &&
				RtlCompareMemory(&Arbiter->Rmd.ConfigSetId, &RegMsg.ConfigSetId, sizeof(GUID)) == sizeof(GUID)
			) {
				if (Arbiter->Status != DRAID_ARBITER_STATUS_TERMINATING) {
					MatchFound = TRUE;
				} else {
					KDPrintM(DBG_LURN_INFO, ("Arbiter is terminating. Reject reception\n"));	
					MatchFound = FALSE;
				}
				break;
			}
		}
		RELEASE_SPIN_LOCK(&g_DraidGlobals->ArbiterListSpinlock, oldIrql);

		if (MatchFound) {
			ResultCode = DRIX_RESULT_SUCCESS;
		} else {
			ResultCode = DRIX_RESULT_RAID_SET_NOT_FOUND;
		}
//reply:
		//
		// Send reply
		//
		Reply.Signature = 	NTOHL(DRIX_SIGNATURE);
		Reply.Command = DRIX_CMD_REGISTER;
		Reply.Length = NTOHS((UINT16)sizeof(DRIX_HEADER));
		Reply.ReplyFlag = 1;
		Reply.Sequence = RegMsg.Header.Sequence;
		Reply.Result = ResultCode;

		Timeout.QuadPart =  HZ * 5;

		KDPrintM(DBG_LURN_INFO, ("DRAID Sending registration reply(result=%x) to remote client\n", ResultCode));
		status = LpxTdiSend(
					Connection->ConnectionFileObject, (PUCHAR)&Reply, sizeof(DRIX_HEADER), 
					0, &Timeout,	NULL, &result	);
		KDPrintM(DBG_LURN_INFO, ("LpxTdiSend status=%x, result=%x.\n", status, result));
		if (status !=STATUS_SUCCESS) {
			Disconnect = TRUE;
			goto out;
		}
		if (MatchFound) {
			status = DraidArbiterAcceptClient(Arbiter, RegMsg.ConnType, Connection);
			if (status == STATUS_SUCCESS) {
				Disconnect = FALSE;
			} else {
				KDPrintM(DBG_LURN_INFO, ("Failed to accept client %x.\n", status));
			}
		}
	} else if (status == STATUS_TIMEOUT) {
		KDPrintM(DBG_LURN_INFO, ("Timeout before registration.\n"));
	}
	
out:
	if (Disconnect) {
		KDPrintM(DBG_LURN_INFO, ("Closing connection to client.\n"));			
		// Close connection.
		LpxTdiDisassociateAddress(Connection->ConnectionFileObject);
		LpxTdiCloseConnection(
					Connection->ConnectionFileHandle, 
					Connection->ConnectionFileObject
					);
		Connection->ConnectionFileHandle = NULL;
		Connection->ConnectionFileObject = NULL;

		ExFreePoolWithTag(Connection, DRAID_REMOTE_CLIENT_CHANNEL_POOL_TAG);
	} else {
		// Arbiter thread will close connection and free channel
	}
	
	KDPrintM(DBG_LURN_INFO, ("Exiting reception thread.\n"));
	// Decrease counter
	InterlockedDecrement(&g_DraidGlobals->ReceptionThreadCount);
}
Exemplo n.º 6
0
/*
 * --------------------------------------------------------------------------
 * OvsCompleteNBL --
 *
 *     This function tries to free the NBL allocated by OVS buffer
 *     management module. If it trigger the completion of the parent
 *     NBL, it will recursively call itself. If it trigger the completion
 *     of external NBL, it will be returned to the caller. The caller
 *     is responsible to call API to return to upper layer.
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsCompleteNBL(POVS_SWITCH_CONTEXT context,
               PNET_BUFFER_LIST nbl,
               BOOLEAN updateRef)
{
    POVS_BUFFER_CONTEXT ctx;
    UINT16 flags;
    PNET_BUFFER_LIST parent;
    NDIS_STATUS status;
    NDIS_HANDLE poolHandle;
    LONG value;
    POVS_NBL_POOL ovsPool = &context->ovsPool;
    PNET_BUFFER nb;


    ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);

    ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);

    OVS_LOG_TRACE("Enter: nbl: %p, ctx: %p, refCount: %d, updateRef:%d",
                 nbl, ctx, ctx->refCount, updateRef);

    if (updateRef) {
        value = InterlockedDecrement((LONG volatile *)&ctx->refCount);
        if (value != 0) {
            return NULL;
        }
    } else {
        /*
         * This is a special case, the refCount must be zero
         */
        ASSERT(ctx->refCount == 0);
    }

    nb = NET_BUFFER_LIST_FIRST_NB(nbl);

    flags = ctx->flags;
    if (!(flags & OVS_BUFFER_FRAGMENT) &&
        NET_BUFFER_DATA_LENGTH(nb) != ctx->origDataLength) {
        UINT32 diff;
        if (NET_BUFFER_DATA_LENGTH(nb) < ctx->origDataLength) {
            diff = ctx->origDataLength -NET_BUFFER_DATA_LENGTH(nb);
            status = NdisRetreatNetBufferListDataStart(nbl, diff, 0,
                                                       NULL, NULL);
            ASSERT(status == NDIS_STATUS_SUCCESS);
        } else {
            diff = NET_BUFFER_DATA_LENGTH(nb) - ctx->origDataLength;
            NdisAdvanceNetBufferListDataStart(nbl, diff, TRUE, NULL);
        }
    }

    if (ctx->flags & OVS_BUFFER_PRIVATE_CONTEXT) {
        NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT));
    }

    if (flags & OVS_BUFFER_NEED_COMPLETE) {
        /*
         * return to caller for completion
         */
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->sysNBLCount);
#endif
        return nbl;
    }

    if (flags & OVS_BUFFER_PRIVATE_FORWARD_CONTEXT) {
        context->NdisSwitchHandlers.
              FreeNetBufferListForwardingContext(ovsPool->ndisContext, nbl);
    }

    if (flags & (OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA)) {
        PNET_BUFFER nb = NET_BUFFER_LIST_FIRST_NB(nbl);
        while (nb) {
            PMDL mdl = NET_BUFFER_FIRST_MDL(nb);
            NET_BUFFER_FIRST_MDL(nb) = NULL;
            ASSERT(mdl->Next == NULL);
            OvsFreeMDLAndData(mdl);
            nb = NET_BUFFER_NEXT_NB(nb);
        }
    }

    if (flags & OVS_BUFFER_PRIVATE_NET_BUFFER) {
        PNET_BUFFER nb, nextNb;

        nb = NET_BUFFER_LIST_FIRST_NB(nbl);
        while (nb) {
            nextNb = NET_BUFFER_NEXT_NB(nb);
            NdisFreeNetBuffer(nb);
#ifdef DBG
            InterlockedDecrement((LONG volatile *)&ovsPool->nbCount);
#endif
            nb = nextNb;
        }
        NET_BUFFER_LIST_FIRST_NB(nbl) = NULL;
    }

    parent = nbl->ParentNetBufferList;

    poolHandle = NdisGetPoolFromNetBufferList(nbl);
    if (flags & OVS_BUFFER_FROM_FIX_SIZE_POOL) {
        ASSERT(poolHandle == ovsPool->fixSizePool);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->fixNBLCount);
#endif
        NdisFreeNetBufferList(nbl);
    } else if (flags & OVS_BUFFER_FROM_ZERO_SIZE_POOL) {
        ASSERT(poolHandle == ovsPool->zeroSizePool);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->zeroNBLCount);
#endif
        NdisFreeNetBufferList(nbl);
    } else if (flags & OVS_BUFFER_FROM_NBL_ONLY_POOL) {
        ASSERT(poolHandle == ovsPool->nblOnlyPool);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->nblOnlyCount);
#endif
        NdisFreeCloneNetBufferList(nbl, 0);
    } else if (flags & OVS_BUFFER_FRAGMENT) {
        OVS_LOG_TRACE("Free fragment %p parent %p", nbl, parent);
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount);
#endif
        NdisFreeFragmentNetBufferList(nbl, ctx->dataOffsetDelta, 0);
    }

    if (parent != NULL) {
        ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(parent);
        ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);
        value = InterlockedDecrement((LONG volatile *)&ctx->refCount);
        if (value == 0) {
            return OvsCompleteNBL(context, parent, FALSE);
        }
    }
    return NULL;
}
Exemplo n.º 7
0
int32_t FastInterlockDecrement(int32_t volatile *lpAddend)
{
    return InterlockedDecrement((LONG *)lpAddend);
}
Exemplo n.º 8
0
Arquivo: main.c Projeto: GYGit/reactos
static ULONG WINAPI Object_Release(IUnknown *iface)
{
    return InterlockedDecrement(&Object_ref);
}
Exemplo n.º 9
0
ClassFactory::~ClassFactory()
{
	InterlockedDecrement(&g_cDllRef);
}
Exemplo n.º 10
0
VOID
KiIpiGenericCallTarget (
    IN PKIPI_CONTEXT SignalDone,
    IN PVOID BroadcastFunction,
    IN PVOID Context,
    IN PVOID Count
    )

/*++

Routine Description:

    This function is the target jacket function to execute a broadcast
    function on a set of target processors. The broadcast packet address
    is obtained, the specified parameters are captured, the broadcast
    packet address is cleared to signal the source processor to continue,
    and the specified function is executed.

Arguments:

    SignalDone Supplies a pointer to a variable that is cleared when the
        requested operation has been performed.

    BroadcastFunction - Supplies the address of function that is executed
        on each of the target processors.

    Context - Supplies the value of the context parameter that is passed
        to each function.

    Count - Supplies the address of a down count synchronization variable.

Return Value:

    None

--*/

{

    //
    // Decrement the synchronization count variable and wait for the value
    // to go to zero.
    //

    InterlockedDecrement((volatile LONG *)Count);
    while ((*(volatile LONG *)Count) != 0) {
        
        //
        // Check for any other IPI such as the debugger
        // while we wait.  Note this routine does a YEILD.
        //

        KiPollFreezeExecution();
    }

    //
    // Execute the specified function.
    //

    ((PKIPI_BROADCAST_WORKER)(ULONG_PTR)(BroadcastFunction))((ULONG_PTR)Context);
    KiIpiSignalPacketDone(SignalDone);
    return;
}
Exemplo n.º 11
0
VOID
ScsiPortRemoveAdapter(
    IN PDEVICE_OBJECT AdapterObject,
    IN BOOLEAN Surprise
    )
{
    PADAPTER_EXTENSION adapter = AdapterObject->DeviceExtension;
    PCOMMON_EXTENSION commonExtension = AdapterObject->DeviceExtension;

    NTSTATUS status = STATUS_SUCCESS;

    PAGED_CODE();

    ASSERT_FDO(AdapterObject);
    ASSERT(adapter->IsPnp);

    //
    // Set the flag PD_ADAPTER_REMOVED to keep scsiport from calling into the 
    // miniport after we've started this teardown.
    //

    if(Surprise == FALSE) {
        PVOID sectionHandle;
        KIRQL oldIrql;

        //
        // Wait until all outstanding requests have been completed.
        //
    
        SpWaitForRemoveLock(AdapterObject, AdapterObject);

        //
        // If the device is started we should uninitialize the miniport and 
        // release it's resources.  Fortunately this is exactly what stop does.  
        //

        if((commonExtension->CurrentPnpState != IRP_MN_SURPRISE_REMOVAL) &&
           ((commonExtension->CurrentPnpState == IRP_MN_START_DEVICE) ||
            (commonExtension->PreviousPnpState == IRP_MN_START_DEVICE))) {

            //
            // Okay.  If this adapter can't support remove then we're dead
            //

            ASSERT(SpIsAdapterControlTypeSupported(adapter, ScsiStopAdapter) == TRUE);

            //
            // Stop the miniport now that it's safe.
            //

            SpEnableDisableAdapter(adapter, FALSE);

            //
            // Mark the adapter as removed.
            //
    
    #ifdef ALLOC_PRAGMA
            sectionHandle = MmLockPagableCodeSection(ScsiPortRemoveAdapter);
            InterlockedIncrement(&SpPAGELOCKLockCount);
    #endif
            KeAcquireSpinLock(&(adapter->SpinLock), &oldIrql);
            adapter->SynchronizeExecution(adapter->InterruptObject,
                                          SpRemoveAdapterSynchronized,
                                          adapter);
    
            KeReleaseSpinLock(&(adapter->SpinLock), oldIrql);
    
    #ifdef ALLOC_PRAGMA
            InterlockedDecrement(&SpPAGELOCKLockCount);
            MmUnlockPagableImageSection(sectionHandle);
    #endif

        }
        SpReapChildren(adapter);
    }

    if(commonExtension->WmiInitialized == TRUE) {

        //
        // Destroy all our WMI resources and unregister with WMI.
        //

        IoWMIRegistrationControl(AdapterObject, WMIREG_ACTION_DEREGISTER);
        SpWmiRemoveFreeMiniPortRequestItems(adapter);
        commonExtension->WmiInitialized = FALSE;
    }

    //
    // If we were surprise removed then this has already been done once.  
    // In that case don't try to run the cleanup code a second time even though 
    // it's safe to do so.
    //

    SpDeleteDeviceMapEntry(AdapterObject);
    SpDestroyAdapter(adapter, Surprise);

    return;
}
Exemplo n.º 12
0
int gettimeofday(struct timeval* tp, int* /*tz*/) {
  static LARGE_INTEGER tickFrequency, epochOffset;

  static Boolean isInitialized = False;

  LARGE_INTEGER tickNow;

#if !defined(_WIN32_WCE)
  QueryPerformanceCounter(&tickNow);
#else
  tickNow.QuadPart = GetTickCount();
#endif
 
  if (!isInitialized) {
    if(1 == InterlockedIncrement(&initializeLock_gettimeofday)) {
#if !defined(_WIN32_WCE)
      // For our first call, use "ftime()", so that we get a time with a proper epoch.
      // For subsequent calls, use "QueryPerformanceCount()", because it's more fine-grain.
      struct timeb tb;
      ftime(&tb);
      tp->tv_sec = tb.time;
      tp->tv_usec = 1000*tb.millitm;

      // Also get our counter frequency:
      QueryPerformanceFrequency(&tickFrequency);
#else
      /* FILETIME of Jan 1 1970 00:00:00. */
      const LONGLONG epoch = 116444736000000000LL;
      FILETIME fileTime;
      LARGE_INTEGER time;
      GetSystemTimeAsFileTime(&fileTime);

      time.HighPart = fileTime.dwHighDateTime;
      time.LowPart = fileTime.dwLowDateTime;

      // convert to from 100ns time to unix timestamp in seconds, 1000*1000*10
      tp->tv_sec = (long)((time.QuadPart - epoch) / 10000000L);

      /*
        GetSystemTimeAsFileTime has just a seconds resolution,
        thats why wince-version of gettimeofday is not 100% accurate, usec accuracy would be calculated like this:
        // convert 100 nanoseconds to usec
        tp->tv_usec= (long)((time.QuadPart - epoch)%10000000L) / 10L;
      */
      tp->tv_usec = 0;

      // resolution of GetTickCounter() is always milliseconds
      tickFrequency.QuadPart = 1000;
#endif     
      // compute an offset to add to subsequent counter times, so we get a proper epoch:
      epochOffset.QuadPart
          = tp->tv_sec * tickFrequency.QuadPart + (tp->tv_usec * tickFrequency.QuadPart) / 1000000L - tickNow.QuadPart;
      
      // next caller can use ticks for time calculation
      isInitialized = True; 
      return 0;
    } else {
        InterlockedDecrement(&initializeLock_gettimeofday);
        // wait until first caller has initialized static values
        while(!isInitialized){
          Sleep(1);
        }
    }
  }

  // adjust our tick count so that we get a proper epoch:
  tickNow.QuadPart += epochOffset.QuadPart;

  tp->tv_sec =  (long)(tickNow.QuadPart / tickFrequency.QuadPart);
  tp->tv_usec = (long)(((tickNow.QuadPart % tickFrequency.QuadPart) * 1000000L) / tickFrequency.QuadPart);

  return 0;
}
Exemplo n.º 13
0
asDWORD asCAtomic::atomicDec()
{
	asASSERT(value > 0);
	return InterlockedDecrement((LONG*)&value);
}
Exemplo n.º 14
0
asDWORD asCAtomic::atomicDec()
{
	return InterlockedDecrement((LONG*)&value);
}
Exemplo n.º 15
0
_CRTIMP void
WINAPI
_freefls (
    void *data
    )

{

    _ptiddata ptd;
    pthreadlocinfo ptloci;
    pthreadmbcinfo ptmbci;

    /*
     * Free up the _tiddata structure & its malloc-ed buffers.
     */

    ptd = data;
    if (ptd != NULL) {
        if(ptd->_errmsg)
            _free_crt((void *)ptd->_errmsg);

        if(ptd->_namebuf0)
            _free_crt((void *)ptd->_namebuf0);

        if(ptd->_namebuf1)
            _free_crt((void *)ptd->_namebuf1);

        if(ptd->_asctimebuf)
            _free_crt((void *)ptd->_asctimebuf);

        if(ptd->_gmtimebuf)
            _free_crt((void *)ptd->_gmtimebuf);

        if(ptd->_cvtbuf)
            _free_crt((void *)ptd->_cvtbuf);

        if (ptd->_pxcptacttab != _XcptActTab)
            _free_crt((void *)ptd->_pxcptacttab);

        _mlock(_MB_CP_LOCK);
        __try {
            if ( ((ptmbci = ptd->ptmbcinfo) != NULL) &&
                 (InterlockedDecrement(&(ptmbci->refcount)) == 0) &&
                 (ptmbci != &__initialmbcinfo) )
                _free_crt(ptmbci);
        }
        __finally {
            _munlock(_MB_CP_LOCK);
        }

        _mlock(_SETLOCALE_LOCK);

        __try {
            if ( (ptloci = ptd->ptlocinfo) != NULL )
            {
                __removelocaleref(ptloci);
                if ( (ptloci != __ptlocinfo) &&
                     (ptloci != &__initiallocinfo) &&
                     (ptloci->refcount == 0) )
                    __freetlocinfo(ptloci);
            }
        }
        __finally {
            _munlock(_SETLOCALE_LOCK);
        }

        _free_crt((void *)ptd);
    }
    return;
}
Exemplo n.º 16
0
VOID
FASTCALL
SpReleaseRemoveLock(
    IN PDEVICE_OBJECT DeviceObject,
    IN OPTIONAL PIRP Tag
)

/*++

Routine Description:

    This routine is called to release the remove lock on the device object.  It
    must be called when finished using a previously locked reference to the
    device object.  If an Tag was specified when acquiring the lock then the
    same Tag must be specified when releasing the lock.

    When the lock count reduces to zero, this routine will signal the waiting
    remove Tag to delete the device object.  As a result the DeviceObject
    pointer should not be used again once the lock has been released.

Arguments:

    DeviceObject - the device object to lock

    Tag - The irp (if any) specified when acquiring the lock.  This is used
          for lock tracking purposes

Return Value:

    none

--*/

{
    PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    LONG lockValue;

#if DBG
    PREMOVE_TRACKING_BLOCK *listEntry =
        &((PREMOVE_TRACKING_BLOCK) commonExtension->RemoveTrackingList);

    BOOLEAN found = FALSE;

    LONGLONG maxCount;

    KIRQL oldIrql;

    if(commonExtension->IsRemoved == REMOVE_COMPLETE) {
        return;
    }

    //
    // Check the tick count and make sure this thing hasn't been locked
    // for more than MaxLockedMinutes.
    //

    maxCount = KeQueryTimeIncrement() * 10;     // microseconds
    maxCount *= 1000;                           // milliseconds
    maxCount *= 1000;                           // seconds
    maxCount *= 60;                             // minutes
    maxCount *= MaxLockedMinutes;

    DebugPrint((4, "SpReleaseRemoveLock: maxCount = %0I64x\n", maxCount));

    KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
                      &oldIrql);

    while(*listEntry != NULL) {

        PREMOVE_TRACKING_BLOCK block;
        LARGE_INTEGER difference;

        block = *listEntry;

        KeQueryTickCount((&difference));

        difference.QuadPart -= block->TimeLocked.QuadPart;

        DebugPrint((4, "SpReleaseRemoveLock: Object %#p (tag %#p) locked "
                    "for %I64d ticks\n", DeviceObject, block->Tag, difference.QuadPart));

        if(difference.QuadPart >= maxCount) {

            DebugPrint((0, ">>>>SpReleaseRemoveLock: Object %#p (tag %#p) locked "
                        "for %I64d ticks - TOO LONG\n", DeviceObject, block->Tag, difference.QuadPart));
            DebugPrint((0, ">>>>SpReleaseRemoveLock: Lock acquired in file "
                        "%s on line %d\n", block->File, block->Line));
            ASSERT(FALSE);
        }

        if((found == FALSE) && ((*listEntry)->Tag == Tag)) {

            *listEntry = block->NextBlock;
            ExFreeToNPagedLookasideList(
                &(commonExtension->RemoveTrackingLookasideList),
                block);
            found = TRUE;

        } else {

            listEntry = &((*listEntry)->NextBlock);

        }
    }

    if(!found) {

        if(commonExtension->RemoveTrackingUntrackedCount == 0) {
            DebugPrint((0, ">>>>SpReleaseRemoveLock: Couldn't find Tag %#p "
                        "in the lock tracking list\n",
                        Tag));
            ASSERT(FALSE);
        } else {

            DebugPrint((0, ">>>>SpReleaseRemoveLock: Couldn't find Tag %#p "
                        "in the lock tracking list - may be one of the "
                        "%d untracked requests still outstanding\n",
                        Tag,
                        commonExtension->RemoveTrackingUntrackedCount));

            commonExtension->RemoveTrackingUntrackedCount--;
            ASSERT(commonExtension->RemoveTrackingUntrackedCount >= 0);
        }
    }

    KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql);

#endif

    lockValue = InterlockedDecrement(&commonExtension->RemoveLock);

    DebugPrint((4, "SpReleaseRemoveLock: Released for Object %#p & irp "
                "%#p - count is %d\n",
                DeviceObject,
                Tag,
                lockValue));

    ASSERT(lockValue >= 0);

    ASSERTMSG("RemoveLock decreased to meet LockLowWatermark",
              ((LockLowWatermark == 0) || !(lockValue == LockLowWatermark)));

    if(lockValue == 0) {

        ASSERT(commonExtension->IsRemoved);

        //
        // The device needs to be removed.  Signal the remove event
        // that it's safe to go ahead.
        //

        DebugPrint((3, "SpReleaseRemoveLock: Release for object %#p & "
                    "irp %#p caused lock to go to zero\n",
                    DeviceObject,
                    Tag));

        KeSetEvent(&commonExtension->RemoveEvent,
                   IO_NO_INCREMENT,
                   FALSE);

    }
    return;
}
Exemplo n.º 17
0
/*
 * --------------------------------------------------------------------------
 * OvsTcpSegmentyNBL --
 *
 *    Segment TCP payload, and prepend each segment with ether/IP/TCP header.
 *    Leave headRoom for additional encap.
 *
 *    Please note,
 *       NBL should have OVS_BUFFER_CONTEXT setup before calling
 *       this function.
 *       The NBL should already have ref to itself so that during copy
 *       it will not be freed.
 *       Currently this API assert there is only one NB in an NBL, it needs
 *       to be fixed if we receive multiple NBs in an NBL.
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsTcpSegmentNBL(PVOID ovsContext,
                 PNET_BUFFER_LIST nbl,
                 POVS_PACKET_HDR_INFO hdrInfo,
                 UINT32 mss,
                 UINT32 headRoom)
{
    POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;
#ifdef DBG
    POVS_NBL_POOL ovsPool = &context->ovsPool;
#endif
    POVS_BUFFER_CONTEXT dstCtx, srcCtx;
    UINT32 size, hdrSize, seqNumber;
    PNET_BUFFER_LIST newNbl;
    PNET_BUFFER nb, newNb;
    NDIS_STATUS status;
    UINT16 segmentSize;
    ULONG copiedSize;

    srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);
    if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) {
        OVS_LOG_INFO("src nbl must have ctx initialized");
        ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC);
        return NULL;
    }

    nb = NET_BUFFER_LIST_FIRST_NB(nbl);
    ASSERT(NET_BUFFER_NEXT_NB(nb) == NULL);

    /* Figure out the segment header size */
    status = GetSegmentHeaderInfo(nbl, hdrInfo, &hdrSize, &seqNumber);
    if (status != NDIS_STATUS_SUCCESS) {
        OVS_LOG_INFO("Cannot parse NBL header");
        return NULL;
    }

    size = NET_BUFFER_DATA_LENGTH(nb) - hdrSize;

    /* XXX add to ovsPool counters? */
    newNbl = NdisAllocateFragmentNetBufferList(nbl, NULL,
            NULL, hdrSize, mss, hdrSize + headRoom , 0, 0);
    if (newNbl == NULL) {
        return NULL;
    }

    /* Now deal with TCP payload */
    for (newNb = NET_BUFFER_LIST_FIRST_NB(newNbl); newNb != NULL;
            newNb = NET_BUFFER_NEXT_NB(newNb)) {
        segmentSize = (size > mss ? mss : size) & 0xffff;
        if (headRoom) {
            NdisAdvanceNetBufferDataStart(newNb, headRoom, FALSE, NULL);
        }

        /* Now copy the eth/IP/TCP header and fix up */
        status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, hdrSize, nb, 0,
                                                  &copiedSize);
        if (status != NDIS_STATUS_SUCCESS || hdrSize != copiedSize) {
            goto nblcopy_error;
        }

        status = FixSegmentHeader(newNb, segmentSize, seqNumber);
        if (status != NDIS_STATUS_SUCCESS) {
            goto nblcopy_error;
        }


        /* Move on to the next segment */
        size -= segmentSize;
        seqNumber += segmentSize;
    }

    status = OvsAllocateNBLContext(context, newNbl);
    if (status != NDIS_STATUS_SUCCESS) {
        goto nblcopy_error;
    }

    status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, hdrSize + headRoom, FALSE);
    if (status != NDIS_STATUS_SUCCESS) {
        goto nbl_context_error;
    }

    newNbl->ParentNetBufferList = nbl;

    /* Remember it's a fragment NBL so we can free it properly */
    dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);
    ASSERT(dstCtx != NULL);
    dstCtx->flags = OVS_BUFFER_FRAGMENT | OVS_BUFFER_PRIVATE_CONTEXT |
        OVS_BUFFER_PRIVATE_FORWARD_CONTEXT | OVS_BUFFER_SEND_BUFFER;
    dstCtx->refCount = 1;
    dstCtx->magic = OVS_CTX_MAGIC;
    dstCtx->dataOffsetDelta = hdrSize + headRoom;

    InterlockedIncrement((LONG volatile *)&srcCtx->refCount);
#ifdef DBG
    InterlockedIncrement((LONG volatile *)&ovsPool->fragNBLCount);

    OvsDumpNetBufferList(nbl);
    OvsDumpForwardingDetails(nbl);

    OvsDumpNetBufferList(newNbl);
    OvsDumpForwardingDetails(newNbl);
#endif
    OVS_LOG_TRACE("Segment nbl %p to newNbl: %p", nbl, newNbl);
    return newNbl;

nbl_context_error:
    OvsFreeNBLContext(context, newNbl);
nblcopy_error:
#ifdef DBG
    InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount);
#endif
    NdisFreeFragmentNetBufferList(newNbl, hdrSize + headRoom, 0);
    return NULL;
}
Exemplo n.º 18
0
// Destructor
Session::~Session()
{
	if (InterlockedDecrement(&(mRefP->mRefCt)) <= 0)
		delete mRefP;
}
Exemplo n.º 19
0
/*
 * --------------------------------------------------------------------------
 * OvsFullCopyNBL --
 *
 *    Copy the NBL to a new NBL including data.
 *
 * Notes:
 *     The NBL can have multiple NBs, but the final result is one NBL.
 * --------------------------------------------------------------------------
 */
PNET_BUFFER_LIST
OvsFullCopyNBL(PVOID ovsContext,
               PNET_BUFFER_LIST nbl,
               UINT32 headRoom,
               BOOLEAN copyNblInfo)
{
    POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;
    POVS_NBL_POOL ovsPool = &context->ovsPool;
    PNET_BUFFER_LIST newNbl;
    PNET_BUFFER nb, newNb, firstNb = NULL, prevNb = NULL;
    POVS_BUFFER_CONTEXT dstCtx, srcCtx;
    PMDL mdl;
    NDIS_STATUS status;
    UINT32 size, totalSize;
    ULONG copiedSize;
    UINT16 flags;
    PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO dstInfo;

    srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);
    if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) {
        OVS_LOG_INFO("src nbl must have ctx initialized");
        ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC);
        return NULL;
    }

    nb = NET_BUFFER_LIST_FIRST_NB(nbl);

    if (NET_BUFFER_NEXT_NB(nb) == NULL) {
        return OvsCopySinglePacketNBL(context, nbl, nb, headRoom, copyNblInfo);
    }

    newNbl = NdisAllocateNetBufferList(ovsPool->nblOnlyPool,
                                       (UINT16)sizeof (OVS_BUFFER_CONTEXT),
                                       (UINT16)OVS_DEFAULT_NBL_CONTEXT_FILL);
    if (newNbl == NULL) {
        return NULL;
    }

    while (nb) {
        size = NET_BUFFER_DATA_LENGTH(nb);
        totalSize = MEM_ALIGN_SIZE(size + headRoom);
        mdl = OvsAllocateMDLAndData(ovsPool->ndisHandle, totalSize);

        if (mdl == NULL) {
            goto nblcopy_error;
        }
        newNb = NdisAllocateNetBuffer(ovsPool->nbPool, mdl, totalSize, 0);
        if (newNb == NULL) {
            OvsFreeMDLAndData(mdl);
            goto nblcopy_error;
        }
        if (firstNb == NULL) {
            firstNb = newNb;
        } else {
            NET_BUFFER_NEXT_NB(prevNb) = newNb;
        }
        prevNb = newNb;
#ifdef DBG
        InterlockedIncrement((LONG volatile *)&ovsPool->nbCount);
#endif
        status = NdisRetreatNetBufferDataStart(newNb, size, 0, NULL);
        ASSERT(status == NDIS_STATUS_SUCCESS);

        status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, size, nb, 0,
                                                  &copiedSize);
        if (status != NDIS_STATUS_SUCCESS || size != copiedSize) {
            goto nblcopy_error;
        }

        nb = NET_BUFFER_NEXT_NB(nb);
    }

    NET_BUFFER_LIST_FIRST_NB(newNbl) = firstNb;

    newNbl->SourceHandle = ovsPool->ndisHandle;
    status = context->NdisSwitchHandlers.
         AllocateNetBufferListForwardingContext(ovsPool->ndisContext, newNbl);

    if (status != NDIS_STATUS_SUCCESS) {
        goto nblcopy_error;
    }

    status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, 0, copyNblInfo);
    if (status != NDIS_STATUS_SUCCESS) {
        goto nblcopy_error;
    }

    dstInfo = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl);
    dstInfo->IsPacketDataSafe = TRUE;

    dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);

    flags = srcCtx->flags & (OVS_BUFFER_RECV_BUFFER | OVS_BUFFER_SEND_BUFFER);

    flags |= OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA |
             OVS_BUFFER_PRIVATE_NET_BUFFER | OVS_BUFFER_FROM_NBL_ONLY_POOL |
             OVS_BUFFER_PRIVATE_FORWARD_CONTEXT;

    OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(firstNb),
                      OVS_DEFAULT_PORT_NO);

#ifdef DBG
    OvsDumpNetBufferList(nbl);
    OvsDumpForwardingDetails(nbl);
    InterlockedIncrement((LONG volatile *)&ovsPool->nblOnlyCount);
#endif
    OVS_LOG_LOUD("newNbl: %p", newNbl);
    return newNbl;

nblcopy_error:
    while (firstNb) {
#ifdef DBG
        InterlockedDecrement((LONG volatile *)&ovsPool->nbCount);
#endif
        prevNb = firstNb;
        firstNb = NET_BUFFER_NEXT_NB(prevNb);
        mdl = NET_BUFFER_FIRST_MDL(prevNb);
        NET_BUFFER_FIRST_MDL(prevNb) = NULL;
        NdisFreeNetBuffer(prevNb);
        OvsFreeMDLAndData(mdl);
    }
    NdisFreeNetBufferList(newNbl);
    OVS_LOG_ERROR("OvsFullCopyNBL failed");
    return NULL;
}
Exemplo n.º 20
0
VOID NTAPI EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt)
{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
    KIRQL oldIrql;
    ULONG newNumPkts;
    
    ASSERT(!Pkt->SlistEntry.Next);

    InterlockedPushEntrySList(&fdoData->FreeTransferPacketsList, &Pkt->SlistEntry);
    newNumPkts = InterlockedIncrement((PLONG)&fdoData->NumFreeTransferPackets);
    ASSERT(newNumPkts <= fdoData->NumTotalTransferPackets);

    /*
     *  If the total number of packets is larger than MinWorkingSetTransferPackets,
     *  that means that we've been in stress.  If all those packets are now
     *  free, then we are now out of stress and can free the extra packets.
     *  Free down to MaxWorkingSetTransferPackets immediately, and
     *  down to MinWorkingSetTransferPackets lazily (one at a time).
     */
    if (fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets){

        /*
         *  1.  Immediately snap down to our UPPER threshold.
         */
        if (fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets){
            SINGLE_LIST_ENTRY pktList;
            PSINGLE_LIST_ENTRY slistEntry;
            PTRANSFER_PACKET pktToDelete;

            DBGTRACE(ClassDebugTrace, ("Exiting stress, block freeing (%d-%d) packets.", fdoData->NumTotalTransferPackets, MaxWorkingSetTransferPackets));

            /*
             *  Check the counter again with lock held.  This eliminates a race condition
             *  while still allowing us to not grab the spinlock in the common codepath.
             *
             *  Note that the spinlock does not synchronize with threads dequeuing free
             *  packets to send (DequeueFreeTransferPacket does that with a lightweight
             *  interlocked exchange); the spinlock prevents multiple threads in this function
             *  from deciding to free too many extra packets at once.
             */
            SimpleInitSlistHdr(&pktList);
            KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
            while ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) && 
                   (fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets)){
                   
                pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);   
                if (pktToDelete){
                    SimplePushSlist(&pktList, &pktToDelete->SlistEntry);
                    InterlockedDecrement((PLONG)&fdoData->NumTotalTransferPackets);    
                }
                else {
                    DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (1).", MaxWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
                    break;
                }
            }
            KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);

            while ((slistEntry = SimplePopSlist(&pktList))){
                pktToDelete = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
                DestroyTransferPacket(pktToDelete);
            }

        }

        /*
         *  2.  Lazily work down to our LOWER threshold (by only freeing one packet at a time).
         */
        if (fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets){
            /*
             *  Check the counter again with lock held.  This eliminates a race condition
             *  while still allowing us to not grab the spinlock in the common codepath.
             *
             *  Note that the spinlock does not synchronize with threads dequeuing free
             *  packets to send (DequeueFreeTransferPacket does that with a lightweight
             *  interlocked exchange); the spinlock prevents multiple threads in this function
             *  from deciding to free too many extra packets at once.
             */
            PTRANSFER_PACKET pktToDelete = NULL; 

            DBGTRACE(ClassDebugTrace, ("Exiting stress, lazily freeing one of %d/%d packets.", fdoData->NumTotalTransferPackets, MinWorkingSetTransferPackets));
            
            KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
            if ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) &&
                (fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets)){
                
                pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);
                if (pktToDelete){
                    InterlockedDecrement((PLONG)&fdoData->NumTotalTransferPackets);    
                }
                else {
                    DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (2).", MinWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
                }
            }
            KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);

            if (pktToDelete){
                DestroyTransferPacket(pktToDelete);
            }
        }

    }
  
}
Exemplo n.º 21
0
////////////////////////////////////////////////////////////////////////////////
// 
// FUNCTION:	CIOCPServer::ThreadPoolFunc 
// 
// DESCRIPTION:	This is the main worker routine for the worker threads.  
//				Worker threads wait on a completion port for I/O to complete.  
//				When it completes, the worker thread processes the I/O, then either pends 
//				new I/O or closes the client's connection.  When the service shuts 
//				down, other code closes the completion port which causes 
//				GetQueuedCompletionStatus() to wake up and the worker thread then 
//				exits.
// 
// INPUTS:		
// 
// NOTES:	
// 
// MODIFICATIONS:
// 
// Name                  Date       Version    Comments
// N T ALMOND            06042001	1.0        Origin
// Ulf Hedlund			 09062001              Changes for OVERLAPPEDPLUS
////////////////////////////////////////////////////////////////////////////////
unsigned CIOCPServer::ThreadPoolFunc (LPVOID thisContext)    
{
	// Get back our pointer to the class
	ULONG ulFlags = MSG_PARTIAL;
	CIOCPServer* pThis = reinterpret_cast<CIOCPServer*>(thisContext);
	ASSERT(pThis);

    HANDLE hCompletionPort = pThis->m_hCompletionPort;
    
    DWORD dwIoSize;
    LPOVERLAPPED   lpOverlapped;
    ClientContext* lpClientContext;
	OVERLAPPEDPLUS*	pOverlapPlus;
	bool			bError;
	bool			bEnterRead;

	InterlockedIncrement(&pThis->m_nCurrentThreads);
	InterlockedIncrement(&pThis->m_nBusyThreads);

	//
    // Loop round and round servicing I/O completions.
	// 

	for (BOOL bStayInPool = TRUE; bStayInPool && pThis->m_bTimeToKill == false; ) 
	{
		pOverlapPlus	= NULL;
		lpClientContext = NULL;
		bError			= false;
		bEnterRead		= false;
		// Thread is Block waiting for IO completion
		InterlockedDecrement(&pThis->m_nBusyThreads);


		// Get a completed IO request.
		BOOL bIORet = GetQueuedCompletionStatus(
               hCompletionPort,
               &dwIoSize,
               (LPDWORD) &lpClientContext,
               &lpOverlapped, INFINITE);

		DWORD dwIOError = GetLastError();
		pOverlapPlus = CONTAINING_RECORD(lpOverlapped, OVERLAPPEDPLUS, m_ol);

		int nBusyThreads = InterlockedIncrement(&pThis->m_nBusyThreads);

        if (!bIORet && dwIOError != WAIT_TIMEOUT )
		{
			if (lpClientContext && pThis->m_bTimeToKill == false)
			{
				pThis->RemoveStaleClient(lpClientContext, FALSE);
			}
			continue;

			// anyway, this was an error and we should exit
			bError = true;
		}
		
		if (!bError) 
		{
			// Allocate another thread to the thread Pool?
			if (nBusyThreads == pThis->m_nCurrentThreads)
			{
				if (nBusyThreads < pThis->m_nThreadPoolMax)
				{
					if (pThis->m_cpu.GetUsage() > pThis->m_nCPUHiThreshold)
					{
						UINT nThreadID = -1;

						HANDLE hThread = (HANDLE)_beginthreadex(NULL,				// Security
											 0,					// Stack size - use default
											 ThreadPoolFunc,  // Thread fn entry point
											 (void*) pThis,	    
											 0,					// Init flag
											 &nThreadID);	// Thread address

						CloseHandle(hThread);
					}
				}
			}


			// Thread timed out - IDLE?
			if (!bIORet && dwIOError == WAIT_TIMEOUT)
			{
				if (lpClientContext == NULL)
				{
					if (pThis->m_cpu.GetUsage() < pThis->m_nCPULoThreshold)
					{
						// Thread has no outstanding IO - Server hasn't much to do so die
						if (pThis->m_nCurrentThreads > pThis->m_nThreadPoolMin)
							bStayInPool =  FALSE;
					}

					bError = true;
				}
			}
		}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
		if (!bError)
		{
			if(bIORet && NULL != pOverlapPlus && NULL != lpClientContext) 
			{
				try
				{
					pThis->ProcessIOMessage(pOverlapPlus->m_ioType, lpClientContext, dwIoSize);
				}
				catch (...) {}
			}
		}

		if(pOverlapPlus)
			delete pOverlapPlus; // from previous call
    }

	InterlockedDecrement(&pThis->m_nWorkerCnt);

	InterlockedDecrement(&pThis->m_nCurrentThreads);
	InterlockedDecrement(&pThis->m_nBusyThreads);
   	return 0;
} 
Exemplo n.º 22
0
NTSTATUS NTAPI TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context)
{
    PTRANSFER_PACKET pkt = (PTRANSFER_PACKET)Context;
    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = pkt->Fdo->DeviceExtension;
    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
    PIO_STACK_LOCATION origCurrentSp = IoGetCurrentIrpStackLocation(pkt->OriginalIrp);
    BOOLEAN packetDone = FALSE;

    /*
     *  Put all the assertions and spew in here so we don't have to look at them.
     */
    DBGCHECKRETURNEDPKT(pkt);    
    
    if (SRB_STATUS(pkt->Srb.SrbStatus) == SRB_STATUS_SUCCESS){
        
        fdoData->LoggedTURFailureSinceLastIO = FALSE;
        
        /*
         *  The port driver should not have allocated a sense buffer
         *  if the SRB succeeded.
         */
        ASSERT(!PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb));

        /*
         *  Add this packet's transferred length to the original IRP's.
         */
        InterlockedExchangeAdd((PLONG)&pkt->OriginalIrp->IoStatus.Information, 
                              (LONG)pkt->Srb.DataTransferLength);

        if (pkt->InLowMemRetry){
            packetDone = StepLowMemRetry(pkt);
        }
        else {
            packetDone = TRUE;
        }
        
    }
    else {
        /*
         *  The packet failed.  We may retry it if possible.
         */
        BOOLEAN shouldRetry;
        
        /*
         *  Make sure IRP status matches SRB error status (since we propagate it).
         */
        if (NT_SUCCESS(Irp->IoStatus.Status)){
            Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        }

        /*
         *  Interpret the SRB error (to a meaningful IRP status)
         *  and determine if we should retry this packet.
         *  This call looks at the returned SENSE info to figure out what to do.
         */
        shouldRetry = InterpretTransferPacketError(pkt);

        /*
         *  Sometimes the port driver can allocates a new 'sense' buffer
         *  to report transfer errors, e.g. when the default sense buffer
         *  is too small.  If so, it is up to us to free it.
         *  Now that we're done interpreting the sense info, free it if appropriate.
         */
        if (PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb)) {
            DBGTRACE(ClassDebugSenseInfo, ("Freeing port-allocated sense buffer for pkt %ph.", pkt));
            FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExt, &pkt->Srb);
            pkt->Srb.SenseInfoBuffer = &pkt->SrbErrorSenseData;
            pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
        }

        /*
         *  If the SRB queue is locked-up, release it.
         *  Do this after calling the error handler.
         */
        if (pkt->Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN){
            ClassReleaseQueue(pkt->Fdo);
        }
        
        if (shouldRetry && (pkt->NumRetries > 0)){           
            packetDone = RetryTransferPacket(pkt);
        }
        else {
            packetDone = TRUE;
        }
        
    }

    /*
     *  If the packet is completed, put it back in the free list.
     *  If it is the last packet servicing the original request, complete the original irp.
     */
    if (packetDone){
        LONG numPacketsRemaining;
        PIRP deferredIrp;
        PDEVICE_OBJECT Fdo = pkt->Fdo;
        UCHAR uniqueAddr;
        
        /*
         *  In case a remove is pending, bump the lock count so we don't get freed
         *  right after we complete the original irp.
         */
        ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddr);        

        /*
         *  The original IRP should get an error code
         *  if any one of the packets failed.
         */
        if (!NT_SUCCESS(Irp->IoStatus.Status)){
            pkt->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;

            /*
             *  If the original I/O originated in user space (i.e. it is thread-queued), 
             *  and the error is user-correctable (e.g. media is missing, for removable media),
             *  alert the user.
             *  Since this is only one of possibly several packets completing for the original IRP,
             *  we may do this more than once for a single request.  That's ok; this allows
             *  us to test each returned status with IoIsErrorUserInduced().
             */
            if (IoIsErrorUserInduced(Irp->IoStatus.Status) &&
                pkt->CompleteOriginalIrpWhenLastPacketCompletes &&
                pkt->OriginalIrp->Tail.Overlay.Thread){

                IoSetHardErrorOrVerifyDevice(pkt->OriginalIrp, pkt->Fdo);
            }
        }

        /*
         *  We use a field in the original IRP to count
         *  down the transfer pieces as they complete.
         */
        numPacketsRemaining = InterlockedDecrement(
            (PLONG)&pkt->OriginalIrp->Tail.Overlay.DriverContext[0]);
            
        if (numPacketsRemaining > 0){
            /*
             *  More transfer pieces remain for the original request.
             *  Wait for them to complete before completing the original irp.
             */
        }
        else {

            /*
             *  All the transfer pieces are done.
             *  Complete the original irp if appropriate.
             */
            ASSERT(numPacketsRemaining == 0);
            if (pkt->CompleteOriginalIrpWhenLastPacketCompletes){  
                if (NT_SUCCESS(pkt->OriginalIrp->IoStatus.Status)){
                    ASSERT((ULONG)pkt->OriginalIrp->IoStatus.Information == origCurrentSp->Parameters.Read.Length);
                    ClasspPerfIncrementSuccessfulIo(fdoExt);
                }
                ClassReleaseRemoveLock(pkt->Fdo, pkt->OriginalIrp);

                ClassCompleteRequest(pkt->Fdo, pkt->OriginalIrp, IO_DISK_INCREMENT);

                /*
                 *  We may have been called by one of the class drivers (e.g. cdrom)
                 *  via the legacy API ClassSplitRequest.  
                 *  This is the only case for which the packet engine is called for an FDO
                 *  with a StartIo routine; in that case, we have to call IoStartNextPacket
                 *  now that the original irp has been completed.
                 */
                if (fdoExt->CommonExtension.DriverExtension->InitData.ClassStartIo) {
                    if (TEST_FLAG(pkt->Srb.SrbFlags, SRB_FLAGS_DONT_START_NEXT_PACKET)){
                        DBGTRAP(("SRB_FLAGS_DONT_START_NEXT_PACKET should never be set here (?)"));
                    }
                    else {
                        KIRQL oldIrql;
                        KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
                        IoStartNextPacket(pkt->Fdo, FALSE);
                        KeLowerIrql(oldIrql);
                    }
                }              
            }            
        }

        /*
         *  If the packet was synchronous, write the final
         *  result back to the issuer's status buffer and
         *  signal his event.
         */
        if (pkt->SyncEventPtr){
            KeSetEvent(pkt->SyncEventPtr, 0, FALSE);
            pkt->SyncEventPtr = NULL;
        }

        /*
         *  Free the completed packet.
         */
        pkt->OriginalIrp = NULL;
        pkt->InLowMemRetry = FALSE;
        EnqueueFreeTransferPacket(pkt->Fdo, pkt);

        /*
         *  Now that we have freed some resources,
         *  try again to send one of the previously deferred irps.
         */
        deferredIrp = DequeueDeferredClientIrp(fdoData);
        if (deferredIrp){
            DBGWARN(("... retrying deferred irp %xh.", deferredIrp)); 
            ServiceTransferRequest(pkt->Fdo, deferredIrp);
        }

        ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddr);        
    }

    return STATUS_MORE_PROCESSING_REQUIRED;
}
Exemplo n.º 23
0
bool CDpiForDialog::SetDialogDPI(const DpiValue& newDpi, LPRECT lprcSuggested /*= NULL*/)
{
	wchar_t szLog[160];
	RECT rcClient = {}, rcCurWnd = {};

	#ifdef _DEBUG
	if (gbSkipSetDialogDPI)
	{
		GetClientRect(mh_Dlg, &rcClient); GetWindowRect(mh_Dlg, &rcCurWnd);
		_wsprintf(szLog, SKIPCOUNT(szLog) L"SKIPPED CDpiForDialog::SetDialogDPI x%08X, OldDpi={%i,%i}, NewDpi={%i,%i}, CurSize={%i,%i}, CurClient={%i,%i}",
			(DWORD)(DWORD_PTR)mh_Dlg, m_CurDpi.Xdpi, m_CurDpi.Ydpi, newDpi.Xdpi, newDpi.Ydpi,
			(rcCurWnd.right - rcCurWnd.left), (rcCurWnd.bottom - rcCurWnd.top),
			(rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top));
		LogString(szLog);
		return false;
	}
	#endif

	if (mn_InSet > 0)
		return false;

	if (newDpi.Ydpi <= 0 || newDpi.Xdpi <= 0)
		return false;
	if (m_CurDpi.Ydpi <= 0 || m_CurDpi.Xdpi <= 0)
		return false;

	// When overall DPI is very large but new dpi is small
	// (example: primary mon is 192 high-dpi, new mon is 96 dpi)
	// Windows goes crazy... HUGE caption, scrollbars, checkbox marks and so on...
	// So huge difference makes dialog unattractive, let's try to smooth that
	DpiValue setDpi(newDpi);
	if (m_InitDpi.Ydpi > MulDiv(setDpi.Ydpi, 144, 96))
	{
		// Increase DPI one step up
		setDpi.Ydpi = MulDiv(setDpi.Ydpi, 120, 96);
		setDpi.Xdpi = MulDiv(setDpi.Xdpi, 120, 96);
		// Log it
		_wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::SetDialogDPI x%08X forces larger dpi value from {%i,%i} to {%i,%i}",
			(DWORD)(DWORD_PTR)mh_Dlg, newDpi.Xdpi, newDpi.Ydpi, setDpi.Xdpi, setDpi.Ydpi);
		LogString(szLog);
	}

	if (m_CurDpi.Equals(setDpi))
		return false;

	bool bRc = false;
	MArray<DlgItem>* p = NULL;
	DpiValue curDpi(m_CurDpi);
	HFONT hf = NULL;

	wchar_t szClass[100];

	#ifdef _DEBUG
	LOGFONT lftest1 = {}, lftest2 = {};
	HFONT hftest;
	int itest1, itest2;
	#endif

	// To avoid several nested passes
	InterlockedIncrement(&mn_InSet);
	m_CurDpi.SetDpi(setDpi);

	// Eval
	mn_CurFontHeight = GetFontSizeForDpi(NULL, m_CurDpi.Ydpi);
	//(m_CurDpi.Ydpi && m_InitDpi.Ydpi) ? (mn_InitFontHeight * m_CurDpi.Ydpi / m_InitDpi.Ydpi) : -11;
	mlf_CurFont = mlf_InitFont;
	mlf_CurFont.lfHeight = mn_CurFontHeight;
	mlf_CurFont.lfWidth = 0; // Font mapper fault

	if (mn_CurFontHeight == 0)
		goto wrap;


	if (!m_Items.Get(m_CurDpi.Ydpi, &p))
	{
		MArray<DlgItem>* pOrig = NULL;
		int iOrigDpi = 0;
		if (!m_Items.GetNext(NULL, &iOrigDpi, &pOrig) || !pOrig || (iOrigDpi <= 0))
			goto wrap;
		int iNewDpi = m_CurDpi.Ydpi;

		p = new MArray<DlgItem>();

		DWORD dwStyle = GetWindowLong(mh_Dlg, GWL_STYLE);
		DWORD dwStyleEx = GetWindowLong(mh_Dlg, GWL_EXSTYLE);

		if (!GetClientRect(mh_Dlg, &rcClient) || !GetWindowRect(mh_Dlg, &rcCurWnd))
		{
			delete p;
			goto wrap;
		}

		_ASSERTE(rcClient.left==0 && rcClient.top==0);
		int calcDlgWidth = rcClient.right * m_CurDpi.Xdpi / curDpi.Xdpi;
		int calcDlgHeight = rcClient.bottom * m_CurDpi.Ydpi / curDpi.Ydpi;

		DlgItem i = {mh_Dlg};

		// Windows DWM manager do not resize NonClient areas of per-monitor dpi aware applications
		// So, we can not use AdjustWindowRectEx to determine full window rectangle
		// Just use current NonClient dimensions
		i.r.right = calcDlgWidth + ((rcCurWnd.right - rcCurWnd.left) - rcClient.right);
		i.r.bottom = calcDlgHeight + ((rcCurWnd.bottom - rcCurWnd.top) - rcClient.bottom);

		// .right and .bottom are width and height of the dialog
		_ASSERTE(i.r.left==0 && i.r.top==0);
		p->push_back(i);

		for (INT_PTR k = 1; k < pOrig->size(); k++)
		{
			const DlgItem& iOrig = (*pOrig)[k];
			i.h = iOrig.h;
			i.r.left = iOrig.r.left * iNewDpi / iOrigDpi;
			i.r.top = iOrig.r.top * iNewDpi / iOrigDpi;
			i.r.right = iOrig.r.right * iNewDpi / iOrigDpi;
			i.r.bottom = iOrig.r.bottom * iNewDpi / iOrigDpi;
			p->push_back(i);
		}

		m_Items.Set(iNewDpi, p);
	}

	if (p->size() <= 0)
	{
		_ASSERTE(FALSE && "No elements");
		goto wrap;
	}
	else
	{
		const DlgItem& di = (*p)[0];
		_wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::SetDialogDPI x%08X, OldDpi={%i,%i}, NewDpi={%i,%i}, OldSize={%i,%i}, NewSize={%i,%i}, NewFont=%i",
			(DWORD)(DWORD_PTR)mh_Dlg, curDpi.Xdpi, curDpi.Ydpi, newDpi.Xdpi, newDpi.Ydpi,
			(rcCurWnd.right - rcCurWnd.left), (rcCurWnd.bottom - rcCurWnd.top), di.r.right, di.r.bottom,
			mlf_CurFont.lfHeight);
		LogString(szLog);
	}

	hf = CreateFontIndirect(&mlf_CurFont);
	if (hf == NULL)
	{
		goto wrap;
	}

	for (INT_PTR k = p->size() - 1; k >= 1; k--)
	{
		const DlgItem& di = (*p)[k];
		GetClassName(di.h, szClass, countof(szClass));
		DWORD nCtrlID = GetWindowLong(di.h, GWL_ID);
		DWORD nStyles = GetWindowLong(di.h, GWL_STYLE);
		bool bResizeCombo = (lstrcmpi(szClass, L"ComboBox") == 0);
		int iComboFieldHeight = 0, iComboWasHeight = 0;
		LONG_PTR lFieldHeight = 0, lNewHeight = 0;
		RECT rcCur = {};
		HWND hComboEdit = NULL;
		RECT rcEdit = {}, rcClient = {};

		if (bResizeCombo && (nStyles & CBS_OWNERDRAWFIXED))
		{
			GetWindowRect(di.h, &rcCur);
			hComboEdit = FindWindowEx(di.h, NULL, L"Edit", NULL);
			GetClientRect(di.h, &rcClient);
			GetClientRect(hComboEdit, &rcEdit);
			iComboWasHeight = (rcCur.bottom - rcCur.top);
			lFieldHeight = SendMessage(di.h, CB_GETITEMHEIGHT, -1, 0);
			if (lFieldHeight < iComboWasHeight)
			{
				iComboFieldHeight = lFieldHeight;
			}
		}

		int newW = di.r.right - di.r.left;
		int newH = di.r.bottom - di.r.top;

		MoveWindow(di.h, di.r.left, di.r.top, newW, newH, FALSE);
		SendMessage(di.h, WM_SETFONT, (WPARAM)hf, FALSE/*immediately*/);
		if (bResizeCombo)
		{
			if ((nStyles & CBS_OWNERDRAWFIXED) && (iComboWasHeight > 0) && (iComboFieldHeight > 0))
			{
				RECT rcEdit2 = {}, rcClient2 = {};
				GetClientRect(di.h, &rcClient2);
				GetClientRect(hComboEdit, &rcEdit2);
				lNewHeight = newH*iComboFieldHeight/iComboWasHeight;
				_wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::Combo height changed - OldHeight=%i, ItemHeight=%i, NewHeight=%i, NewItemHeight=%i",
					(rcCur.bottom - rcCur.top), lFieldHeight, newH, lNewHeight);
				LogString(szLog);
				SendMessage(di.h, CB_SETITEMHEIGHT, -1, lNewHeight);
			}
			SendMessage(di.h, CB_SETEDITSEL, 0, MAKELPARAM(-1,0));
		}
		EditIconHint_ResChanged(di.h);
		InvalidateRect(di.h, NULL, TRUE);
		#ifdef _DEBUG
		itest1 = GetObject(hf, sizeof(lftest1), &lftest1);
		hftest = (HFONT)SendMessage(di.h, WM_GETFONT, 0, 0);
		itest2 = GetObject(hftest, sizeof(lftest2), &lftest2);
		#endif
	}

	if (p->size() > 0)
	{
		const DlgItem& di = (*p)[0];
		SendMessage(mh_Dlg, WM_SETFONT, (WPARAM)hf, FALSE);
		DWORD nWndFlags = SWP_NOZORDER | (lprcSuggested ? 0 : SWP_NOMOVE);
		SetWindowPos(mh_Dlg, NULL,
			lprcSuggested ? lprcSuggested->left : 0, lprcSuggested ? lprcSuggested->top : 0,
			di.r.right, di.r.bottom,
			nWndFlags);
		RECT rc = {}; GetClientRect(mh_Dlg, &rc);
		InvalidateRect(mh_Dlg, NULL, TRUE);
		RedrawWindow(mh_Dlg, &rc, NULL, /*RDW_ERASE|*/RDW_ALLCHILDREN/*|RDW_INVALIDATE|RDW_UPDATENOW|RDW_INTERNALPAINT*/);
	}

	if (mh_CurFont != hf)
		DeleteObject(mh_CurFont);
	mh_CurFont = hf;

	bRc = true;
wrap:
	InterlockedDecrement(&mn_InSet);
	return bRc;
}
Exemplo n.º 24
0
void release_service(struct service_entry *service)
{
    if (InterlockedDecrement(&service->ref_count) == 0 && is_marked_for_delete(service))
        free_service_entry(service);
}
Exemplo n.º 25
0
static ULONG WINAPI DICF_Release(LPCLASSFACTORY iface) {
  IClassFactoryImpl *This = impl_from_IClassFactory(iface);
  /* static class, won't be  freed */
  return InterlockedDecrement(&This->ref);
}
Exemplo n.º 26
0
static void xmlnode_release(xmlNodePtr node)
{
    if (node->type == XML_DOCUMENT_NODE) return;
    InterlockedDecrement((LONG*)&node->_private);
}
Exemplo n.º 27
0
CShellExtClassFactory::~CShellExtClassFactory()
{
    InterlockedDecrement(&g_cRefThisDll);
}
Exemplo n.º 28
0
NTSTATUS
NdasFsSecondaryPreOperationCallback (
	IN PCFLT_RELATED_OBJECTS	FltObjects,
	IN PCTX_INSTANCE_CONTEXT	InstanceContext,
	IN OUT PFLT_CALLBACK_DATA	Data
	)
{
	NTSTATUS				status = FLT_PREOP_SUCCESS_NO_CALLBACK;
	//PIO_STACK_LOCATION	iopb = IoGetCurrentIrpStackLocation( Irp );
	PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
	PFILE_OBJECT			fileObject = iopb->TargetFileObject;
	BOOLEAN					fastMutexAcquired = FALSE;


	//UNREFERENCED_PARAMETER( DeviceObject );
	UNREFERENCED_PARAMETER( FltObjects );

	ASSERT( KeGetCurrentIrql() <= APC_LEVEL );

	LfsDeviceExt_Reference( &InstanceContext->LfsDeviceExt );	

	InterlockedIncrement( &InstanceContext->LfsDeviceExt.ProcessingIrpCount );

	ExAcquireFastMutex( &InstanceContext->LfsDeviceExt.FastMutex );
	fastMutexAcquired = TRUE;
	
	try {

		if (iopb->MajorFunction == IRP_MJ_WRITE) {

			if (InstanceContext->LfsDeviceExt.Secondary == NULL ||
				Secondary_LookUpFileExtension(InstanceContext->LfsDeviceExt.Secondary, fileObject) == NULL) {

				SPY_LOG_PRINT( LFS_DEBUG_LFS_TRACE, ("LfsPassThrough Fake Write %wZ\n", &fileObject->FileName) );

				Data->IoStatus.Status = STATUS_SUCCESS;
				Data->IoStatus.Information = 0;

				status = FLT_PREOP_COMPLETE;
				leave;
			}
		}

		if (iopb->MajorFunction == IRP_MJ_CREATE) {

			//UNICODE_STRING	Extend = { 16, 16, L"\\$Extend" };
			//UNICODE_STRING	tempUnicode;

			if (IsMetaFile(&fileObject->FileName)) {

				status = FLT_PREOP_SUCCESS_NO_CALLBACK;
				leave;
			}

			if (RtlEqualUnicodeString(&GlobalLfs.MountMgrRemoteDatabase, &fileObject->FileName, TRUE)	|| 
				RtlEqualUnicodeString(&GlobalLfs.ExtendReparse, &fileObject->FileName, TRUE)			||
				RtlEqualUnicodeString(&GlobalLfs.MountPointManagerRemoteDatabase, &fileObject->FileName, TRUE)) {

				SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, 
							  ("LfsPassThrough: %wZ returned with STATUS_OBJECT_NAME_NOT_FOUND\n", &fileObject->FileName) );

				NDASFS_ASSERT( FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_MOUNTED) );

				if (FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_MOUNTED)) {

					Data->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
					Data->IoStatus.Information = 0;

					status = FLT_PREOP_COMPLETE;
				
				} else {

					status = FLT_PREOP_SUCCESS_NO_CALLBACK;
				}

				leave;
			}

			if ((fileObject->FileName.Length == (sizeof(REMOUNT_VOLUME_FILE_NAME)-sizeof(WCHAR)) && 
				 RtlEqualMemory(fileObject->FileName.Buffer, REMOUNT_VOLUME_FILE_NAME, fileObject->FileName.Length)) ||
				(fileObject->FileName.Length == (sizeof(TOUCH_VOLUME_FILE_NAME)-sizeof(WCHAR)) && 
				 RtlEqualMemory(fileObject->FileName.Buffer, TOUCH_VOLUME_FILE_NAME, fileObject->FileName.Length))) {

				//PrintData( LFS_DEBUG_LFS_TRACE, "TOUCH/REMOUNT_VOLUME_FILE_NAME", &InstanceContext->LfsDeviceExt, Irp );

				Data->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
				Data->IoStatus.Information = 0;

				status = FLT_PREOP_COMPLETE;
				leave;
			}

			//PrintData( LFS_DEBUG_LFS_NOISE, __FUNCTION__, &InstanceContext->LfsDeviceExt, Irp );
		}

		if (!FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_MOUNTED)) {

			status = FLT_PREOP_SUCCESS_NO_CALLBACK;
			leave;
		}

		if (FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTED)) {

			status = FLT_PREOP_SUCCESS_NO_CALLBACK;
			leave;
		}

		if (FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTING)) {

			NDASFS_ASSERT( InstanceContext->LfsDeviceExt.Secondary == NULL || 
						   Secondary_LookUpFileExtension(InstanceContext->LfsDeviceExt.Secondary, fileObject) == NULL );

			status = FLT_PREOP_SUCCESS_NO_CALLBACK;
			leave;
		}

		NDASFS_ASSERT( FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_MOUNTED) && !FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTED) );

		if (FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_SURPRISE_REMOVED)) {

			if (Secondary_LookUpFileExtension(InstanceContext->LfsDeviceExt.Secondary, fileObject)) {

				if (iopb->MajorFunction == IRP_MJ_CLOSE) {

					SecondaryFileObjectClose( InstanceContext->LfsDeviceExt.Secondary, Data->Iopb->TargetFileObject );
		
					Data->IoStatus.Status = STATUS_SUCCESS;
					Data->IoStatus.Information = 0;

					status = FLT_PREOP_COMPLETE;
					leave;
				} 
				
				if (iopb->MajorFunction == IRP_MJ_PNP) {

					status = FLT_PREOP_SUCCESS_NO_CALLBACK;
					leave;
				} 

				if (iopb->MajorFunction == IRP_MJ_CLEANUP) {

					InterlockedDecrement( &((PLFS_FCB)iopb->TargetFileObject->FsContext)->UncleanCount );
					SetFlag( fileObject->Flags, FO_CLEANUP_COMPLETE );

					Data->IoStatus.Status = STATUS_SUCCESS;
					Data->IoStatus.Information = 0;
				
				} else {
				
					Data->IoStatus.Status = STATUS_DEVICE_REMOVED;
					Data->IoStatus.Information = 0;
				}

				status = FLT_PREOP_COMPLETE;
				leave;
			}

			status = FLT_PREOP_SUCCESS_NO_CALLBACK;
			leave;
		}

		if (iopb->MajorFunction == IRP_MJ_PNP) {

			switch (iopb->MinorFunction) {

			case IRP_MN_SURPRISE_REMOVAL: {
				
				PNETDISK_PARTITION	netdiskPartition2;

				NDASFS_ASSERT( InstanceContext->LfsDeviceExt.NetdiskPartition );
				
				netdiskPartition2 = InstanceContext->LfsDeviceExt.NetdiskPartition;
				InstanceContext->LfsDeviceExt.NetdiskPartition = NULL;

				SetFlag( InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_SURPRISE_REMOVED );

				ExReleaseFastMutex( &InstanceContext->LfsDeviceExt.FastMutex );
				fastMutexAcquired = FALSE;

				NetdiskManager_SurpriseRemoval( GlobalLfs.NetdiskManager,
												netdiskPartition2,
												InstanceContext->LfsDeviceExt.NetdiskEnabledMode );

				status = FLT_PREOP_SUCCESS_NO_CALLBACK;
				leave;
			} 
		
			case IRP_MN_QUERY_REMOVE_DEVICE: {
							
				//KEVENT				waitEvent;

				if (InstanceContext->LfsDeviceExt.ProcessingIrpCount != 1) {

					Data->IoStatus.Status = STATUS_UNSUCCESSFUL;
					Data->IoStatus.Information = 0;

					status = FLT_PREOP_COMPLETE;
					leave;
				}

				if (InstanceContext->LfsDeviceExt.SecondaryState == VOLUME_PURGE_STATE) {
					
					Data->IoStatus.Status = STATUS_UNSUCCESSFUL;
					Data->IoStatus.Information = 0;

					status = FLT_PREOP_COMPLETE;
					leave;
				}
			
				if (FlagOn(InstanceContext->LfsDeviceExt.Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {  // While Disabling and disconnected
	
					Data->IoStatus.Status = STATUS_UNSUCCESSFUL;
					Data->IoStatus.Information = 0;

					status = FLT_PREOP_COMPLETE;
					leave;
				}

				SPY_LOG_PRINT( LFS_DEBUG_SECONDARY_TRACE, ("Secondary_PassThrough: IRP_MN_QUERY_REMOVE_DEVICE Entered\n") );

				ExReleaseFastMutex( &InstanceContext->LfsDeviceExt.FastMutex );
				fastMutexAcquired = FALSE;

				Secondary_TryCloseFilExts( InstanceContext->LfsDeviceExt.Secondary );
			
				if (!IsListEmpty(&InstanceContext->LfsDeviceExt.Secondary->FcbQueue)) {

					LARGE_INTEGER interval;
				
					// Wait all files closed
					interval.QuadPart = (1 * DELAY_ONE_SECOND);      //delay 1 seconds
					KeDelayExecutionThread( KernelMode, FALSE, &interval );
				}
			
				if (!IsListEmpty(&InstanceContext->LfsDeviceExt.Secondary->FcbQueue)) {

					Data->IoStatus.Status = STATUS_UNSUCCESSFUL;
					Data->IoStatus.Information = 0;

					status = FLT_PREOP_COMPLETE;
					leave;
				} 
			
				NDASFS_ASSERT( InstanceContext->LfsDeviceExt.AttachedToDeviceObject );
			
				ExAcquireFastMutex( &InstanceContext->LfsDeviceExt.FastMutex );
				fastMutexAcquired = TRUE;

				SetFlag( InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTING );

#if 0

				IoCopyCurrentIrpStackLocationToNext( Irp );
				KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );

				IoSetCompletionRoutine( Irp,
										LfsPassThroughCompletion,
										&waitEvent,
										TRUE,
										TRUE,
										TRUE );

				status = IoCallDriver( InstanceContext->LfsDeviceExt.AttachedToDeviceObject, Irp );

				if (status == STATUS_PENDING) {

					status = KeWaitForSingleObject( &waitEvent, Executive, KernelMode, FALSE, NULL );
					ASSERT( status == STATUS_SUCCESS );
				}

				ASSERT( KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Data->IoStatus.Status) );
	
				SPY_LOG_PRINT( LFS_DEBUG_SECONDARY_INFO, 
							   ("%s: lfsDeviceExt = %p, IRP_MN_QUERY_REMOVE_DEVICE Data->IoStatus.Status = %x\n",
								__FUNCTION__, &InstanceContext->LfsDeviceExt, Data->IoStatus.Status) );

				ClearFlag( InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTING );

				if (NT_SUCCESS(Data->IoStatus.Status)) {

					ASSERT( !FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTED) );
					LfsDismountVolume( &InstanceContext->LfsDeviceExt );
				}

				status = Data->IoStatus.Status;
				IoCompleteRequest( Irp, IO_NO_INCREMENT );

				result = TRUE;
				leave;
#else
				status = FLT_PREOP_SUCCESS_WITH_CALLBACK;
				leave;
#endif
			}

			case IRP_MN_REMOVE_DEVICE:

				NDASFS_ASSERT( FALSE );
	
			default:

				status = FLT_PREOP_SUCCESS_NO_CALLBACK;
				leave;
			}
		}
		
		if (iopb->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) {

			if (iopb->MinorFunction == IRP_MN_USER_FS_REQUEST || iopb->MinorFunction == IRP_MN_KERNEL_CALL) {

				switch (iopb->Parameters.FileSystemControl.Common.FsControlCode) {

				case FSCTL_LOCK_VOLUME: 
					
					if (InstanceContext->LfsDeviceExt.SecondaryState == VOLUME_PURGE_STATE) {

						status = FLT_PREOP_SUCCESS_NO_CALLBACK;
						leave;
					}

					SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO,
								   ("LfsPassThrough, IRP_MJ_FILE_SYSTEM_CONTROL: Return failure of acquiring the volume exclusively.\n") );

					NDASFS_ASSERT( fileObject && fileObject->FileName.Length == 0 && fileObject->RelatedFileObject == NULL );

					Data->IoStatus.Status = STATUS_ACCESS_DENIED;
					Data->IoStatus.Information = 0;

					status = FLT_PREOP_COMPLETE;
					leave;
									
				case FSCTL_DISMOUNT_VOLUME: {

					//KEVENT				waitEvent;

					ASSERT( IS_WINDOWSVISTA_OR_LATER() );

					ExReleaseFastMutex( &InstanceContext->LfsDeviceExt.FastMutex );
					fastMutexAcquired = FALSE;

					Secondary_TryCloseFilExts( InstanceContext->LfsDeviceExt.Secondary );
		
					if (!IsListEmpty(&InstanceContext->LfsDeviceExt.Secondary->FcbQueue)) {

						LARGE_INTEGER interval;
				
						// Wait all files closed
						interval.QuadPart = (2 * DELAY_ONE_SECOND);      //delay 1 seconds
						KeDelayExecutionThread( KernelMode, FALSE, &interval );
					}
			
					if (!IsListEmpty(&InstanceContext->LfsDeviceExt.Secondary->FcbQueue)) {

						NDASFS_ASSERT( FALSE );

						Data->IoStatus.Status = STATUS_UNSUCCESSFUL;
						Data->IoStatus.Information = 0;

						status = FLT_PREOP_COMPLETE;
						leave;
					} 

					ExAcquireFastMutex( &InstanceContext->LfsDeviceExt.FastMutex );
					fastMutexAcquired = TRUE;

					SetFlag( InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTING );

#if 0

					IoCopyCurrentIrpStackLocationToNext( Irp );
					KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );

					IoSetCompletionRoutine( Irp,
											LfsPassThroughCompletion,
											&waitEvent,
											TRUE,
											TRUE,
											TRUE );

					status = IoCallDriver( InstanceContext->LfsDeviceExt.AttachedToDeviceObject, Irp );

					if (status == STATUS_PENDING) {

						status = KeWaitForSingleObject( &waitEvent, Executive, KernelMode, FALSE, NULL );
						ASSERT( status == STATUS_SUCCESS );
					}

					ASSERT( KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Data->IoStatus.Status) );

					ClearFlag( InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTING );
	
					if (NT_SUCCESS(Data->IoStatus.Status)) {

						ASSERT( !FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTED) );
						LfsDismountVolume( &InstanceContext->LfsDeviceExt );
					}

					status = Data->IoStatus.Status;
					IoCompleteRequest( Irp, IO_NO_INCREMENT );

					SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, 
								   ("%s: FSCTL_DISMOUNT_VOLUME Data->IoStatus.Status = %x\n",
									__FUNCTION__, Data->IoStatus.Status) );

					result = TRUE;
					leave;
#else
					status = FLT_PREOP_SUCCESS_WITH_CALLBACK;
					leave;
#endif
				}

				default:

					break;
				}
			}
		}

		if (iopb->MajorFunction != IRP_MJ_CREATE && 
			Secondary_LookUpFileExtension(InstanceContext->LfsDeviceExt.Secondary, fileObject) == NULL) {

			status = FLT_PREOP_SUCCESS_NO_CALLBACK;
			leave;
		} 

		if (InstanceContext->LfsDeviceExt.SecondaryState == WAIT_PURGE_SAFE_STATE) {

			NDASFS_ASSERT( iopb->MajorFunction == IRP_MJ_CREATE );

			if ((fileObject->FileName.Length == (sizeof(WAKEUP_VOLUME_FILE_NAME)-sizeof(WCHAR)) && 
				 RtlEqualMemory(fileObject->FileName.Buffer, WAKEUP_VOLUME_FILE_NAME, fileObject->FileName.Length)) || 
				(fileObject->FileName.Length == (sizeof(TOUCH_VOLUME_FILE_NAME)-sizeof(WCHAR)) && 
				 RtlEqualMemory(fileObject->FileName.Buffer, TOUCH_VOLUME_FILE_NAME, fileObject->FileName.Length))) {

				 //PrintData( LFS_DEBUG_LFS_INFO, "LfsPassThrough WAIT_PURGE_SAFE_STATE", &InstanceContext->LfsDeviceExt, Irp );

				 Data->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
				 Data->IoStatus.Information = 0;

				 status = FLT_PREOP_COMPLETE;
				 leave;
			}		

			//PrintData( LFS_DEBUG_LFS_INFO, "LfsPassThrough WAIT_PURGE_SAFE_STATE", &InstanceContext->LfsDeviceExt, Irp );

			if (Data->RequestorMode == UserMode && fileObject && fileObject->FileName.Length) {

				InstanceContext->LfsDeviceExt.SecondaryState = SECONDARY_STATE;
			
			} else {

				status = FLT_PREOP_SUCCESS_NO_CALLBACK;
				leave;
			}
		}

		if (InstanceContext->LfsDeviceExt.SecondaryState == VOLUME_PURGE_STATE) {

			if (iopb->MajorFunction == IRP_MJ_CREATE) {

				if (fileObject->FileName.Length == (sizeof(WAKEUP_VOLUME_FILE_NAME)-sizeof(WCHAR)) && 
					RtlEqualMemory(fileObject->FileName.Buffer, WAKEUP_VOLUME_FILE_NAME, fileObject->FileName.Length)) {

					//PrintData( LFS_DEBUG_LFS_TRACE, "WAKEUP_VOLUME_FILE_NAME", &InstanceContext->LfsDeviceExt, Irp );

					Data->IoStatus.Status = STATUS_PORT_DISCONNECTED;
					Data->IoStatus.Information = 0;

					status = FLT_PREOP_COMPLETE;
					leave;
				}

				if (Data->RequestorMode == KernelMode &&
					(fileObject->RelatedFileObject == NULL ||
					 Secondary_LookUpFileExtension(InstanceContext->LfsDeviceExt.Secondary, fileObject->RelatedFileObject) == NULL)) {

					//PrintData( LFS_DEBUG_LFS_INFO, "LfsPassThrough VOLUME_PURGE_STATE", &InstanceContext->LfsDeviceExt, Irp );
					//ASSERT( fileObject->FileName.Length == 0 );

					status = FLT_PREOP_SUCCESS_NO_CALLBACK;
					leave;
				}
			}
		}

		ExReleaseFastMutex( &InstanceContext->LfsDeviceExt.FastMutex );
		fastMutexAcquired = FALSE;

		NDASFS_ASSERT( fileObject );

		if ((FlagOn(InstanceContext->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_INDIRECT) && InstanceContext->LfsDeviceExt.FileSystemType == LFS_FILE_SYSTEM_NDAS_FAT) ||
			InstanceContext->LfsDeviceExt.FileSystemType == LFS_FILE_SYSTEM_FAT) {

			if (InstanceContext->LfsDeviceExt.SecondaryState == CONNECTED_TO_LOCAL_STATE) {

				if (fileObject != NULL &&
					Secondary_LookUpFileExtension(InstanceContext->LfsDeviceExt.Secondary, fileObject) == NULL && 
					(fileObject->RelatedFileObject == NULL ||
					Secondary_LookUpFileExtension(InstanceContext->LfsDeviceExt.Secondary, fileObject->RelatedFileObject) == NULL)) {

					status = FLT_PREOP_SUCCESS_NO_CALLBACK;
					leave;
				} 
			}
		}

		status = MiniSecondaryNtfsPassThrough( InstanceContext->LfsDeviceExt.Secondary, Data );

	} finally {

		InterlockedDecrement( &InstanceContext->LfsDeviceExt.ProcessingIrpCount );

		if (fastMutexAcquired)
			ExReleaseFastMutex( &InstanceContext->LfsDeviceExt.FastMutex );

		LfsDeviceExt_Dereference( &InstanceContext->LfsDeviceExt );
	}

	return status;
}
Exemplo n.º 29
0
VOID UnlockModule()
{
	InterlockedDecrement(&g_nLockCount);
}
Exemplo n.º 30
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
                    //

                    AFSTearDownFcbExtents( pFcb,
                                           &pCcb->AuthGroup);
                }
                else
                {

                    if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
                        pFcb->Specific.File.ExtentsDirtyCount &&
                        (pCcb->GrantedAccess & FILE_WRITE_DATA))
                    {

                        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( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
    {

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

        AFSDumpTraceFilesFnc();
    }

    return ntStatus;
}