Beispiel #1
0
VOID 
HotKeyKrnlUnload(
    IN PDRIVER_OBJECT DriverObject
    )
{ 
	PDEVICE_OBJECT  DeviceObject; 
	LARGE_INTEGER   lDelay;
	KdPrint(("[shadow] Enter HotKeyKrnlUnload...\n"));
	KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
	
    // Delete device we have created
	DeviceObject = DriverObject->DeviceObject;
	while (DeviceObject)
	{
		if (((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDeviceObject)
			HotKeyKrnlDetach(DeviceObject);
		else
			IoDeleteDevice(DeviceObject);
		DeviceObject = DeviceObject->NextDevice;
	}
	if (gKeyCount > 0 && PendingIrp)
	{
		if (!CancelKeyboardIrp(PendingIrp))
			KdPrint(("[shadow] Cancel irp failed\n"));
	}

    lDelay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND);
    while (gKeyCount) {
		KeDelayExecutionThread(KernelMode, FALSE, &lDelay);
    }
	KdPrint(("[shadow] Exit HotKeyKrnlUnload...\n"));
}
Beispiel #2
0
NTSTATUS HelloDDKQueryInfomation(IN PDEVICE_OBJECT pDevObj,
								 IN PIRP pIrp) 
{
	KdPrint(("Enter HelloDDKQueryInfomation\n"));

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

	FILE_INFORMATION_CLASS info = stack->Parameters.QueryFile.FileInformationClass;
	if (info==FileStandardInformation )
	{
		KdPrint(("FileStandardInformation\n"));
		PFILE_STANDARD_INFORMATION file_info  = 
			(PFILE_STANDARD_INFORMATION)pIrp->AssociatedIrp.SystemBuffer;
		file_info->EndOfFile = RtlConvertLongToLargeInteger(pDevExt->file_length);
	}

	NTSTATUS status = STATUS_SUCCESS;
	// 完成IRP
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = stack->Parameters.QueryFile.Length;	// bytes xfered
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );

	KdPrint(("Leave HelloDDKQueryInfomation\n"));

	return status;
}
Beispiel #3
0
/****************************************************************************
REMARKS:
Function to register a driver heart beat callback function. The first
function that is called sets the interval for all the callback functions
and they will be called in the order they were registered. This function
will implement this mechanism in whatever way is appropriate for the
device driver environment.

Note that currently there is no mechanism to specify the timer intervals at
run-time, so we use a pre-determined value of 32 milliseconds that will be
useful for NT display driver polling and DPVL update functions.
****************************************************************************/
void PMAPI PM_registerHeartBeatCallback(
    PM_heartBeat_cb cb,
    void *data)
{
    // Kernel objects must always be resident in memory
    if (_PM_hb == NULL) {
        _PM_hb = ExAllocatePool(NonPagedPool, sizeof(_PM_heartBeat_t));
        if (_PM_hb == NULL)
            return;
        RtlZeroMemory(_PM_hb, sizeof(_PM_heartBeat_t));
        }

    // If first time called, start periodic timer (pre-determined intervals)
    if (_PM_hb->numHeartBeatCallbacks == 0) {
        KeInitializeTimer(&_PM_hb->kTimer);
        KeInitializeDpc(&_PM_hb->kTimerDpc,_PM_heartBeatTimeout,(void*)_PM_hb);
        KeSetTimerEx(&_PM_hb->kTimer,RtlConvertLongToLargeInteger(-10000*HEART_BEAT_MS),
            HEART_BEAT_MS,&_PM_hb->kTimerDpc);
        KeInitializeEvent(&_PM_hb->kTimerEvent,NotificationEvent,FALSE);
        // Callbacks will be executed within driver helper thread, not DPC
        _PM_hb->bThreadRunning = true;
        PsCreateSystemThread(&_PM_hb->hDriverThread,THREAD_ALL_ACCESS,NULL,
            NULL,NULL,_PM_heartBeatThread,(void*)_PM_hb);
        }

    // Add heart beat callback to list
    PM_lockSNAPAccess(-1,true);
    if (_PM_hb->numHeartBeatCallbacks < MAX_HEART_BEAT_CALLBACKS) {
        _PM_hb->heartBeat[_PM_hb->numHeartBeatCallbacks] = cb;
        _PM_hb->heartBeatData[_PM_hb->numHeartBeatCallbacks] = data;
        _PM_hb->numHeartBeatCallbacks++;
        }
    PM_unlockSNAPAccess(-1);
}
Beispiel #4
0
VOID
SoundDelay(
    IN ULONG Milliseconds
)
/*++

Routine Description :

    Stall the current thread for the given number of milliseconds AT LEAST

Arguments :

    Milliseconds - number of milliseconds to delay

Return Value :

    None

--*/
{
    LARGE_INTEGER Delay;

    //
    // Can't call SoundDelay() from high irql
    //

    if (KeGetCurrentIrql() >= DISPATCH_LEVEL) {
        return;
    }

    //
    // First a tiny delay to synch us up with the timer otherwise we
    // may wait up to 15ms less time than we expected!
    //

    Delay = RtlConvertLongToLargeInteger(-1);

    KeDelayExecutionThread(KernelMode,
                           FALSE,         // Not alertable
                           &Delay);

    Delay = RtlConvertLongToLargeInteger((-(LONG)Milliseconds) * 10000);

    KeDelayExecutionThread(KernelMode,
                           FALSE,         // Not alertable
                           &Delay);
}
Beispiel #5
0
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
								 IN PIRP pIrp) 
{
	KdPrint(("DriverB:Enter B HelloDDKRead\n"));
	NTSTATUS ntStatus = STATUS_SUCCESS;

	UNICODE_STRING DeviceName;
	RtlInitUnicodeString( &DeviceName, L"\\Device\\MyDDKDeviceA" );

	//初始化objectAttributes
	OBJECT_ATTRIBUTES objectAttributes;
	InitializeObjectAttributes(&objectAttributes, 
							&DeviceName,
							OBJ_CASE_INSENSITIVE, 
							NULL, 
							NULL );

	HANDLE hDevice;
	IO_STATUS_BLOCK status_block;
	
	//异步打开设备
	ntStatus = ZwCreateFile(&hDevice,
		FILE_READ_ATTRIBUTES,//没有设SYNCHRONIZE
		&objectAttributes,
		&status_block,
		NULL,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ,
		FILE_OPEN_IF,0,NULL,0);

	LARGE_INTEGER offset = RtlConvertLongToLargeInteger(0);
	if (NT_SUCCESS(ntStatus))
	{
		ntStatus = ZwReadFile(hDevice,NULL,NULL,NULL,&status_block,NULL,0,&offset,NULL);
	}

	if (ntStatus==STATUS_PENDING)
	{
		KdPrint(("DriverB:ZwReadFile return STATUS_PENDING!\n"));

		PFILE_OBJECT FileObject;
		ntStatus = ObReferenceObjectByHandle(hDevice, EVENT_MODIFY_STATE, *ExEventObjectType,
						KernelMode, (PVOID*) &FileObject, NULL);
		if (NT_SUCCESS(ntStatus))
		{
			KdPrint(("DriverB:Waiting..."));
			KeWaitForSingleObject(&FileObject->Event,Executive,KernelMode,FALSE,NULL);
			KdPrint(("DriverB:Driver A Read IRP completed now!\n"));
			ObDereferenceObject(FileObject);
		}
	}
	ZwClose(hDevice);

	ntStatus = STATUS_SUCCESS;
	// 完成IRP
	pIrp->IoStatus.Status = ntStatus;
	pIrp->IoStatus.Information = 0;	// bytes xfered
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
	KdPrint(("DriverB:Leave B HelloDDKRead\n"));
	return ntStatus;
}
Beispiel #6
0
BOOLEAN Sleep(ULONG MillionSecond)
{
	NTSTATUS st;
	LARGE_INTEGER DelayTime;
	DelayTime = RtlConvertLongToLargeInteger(-10000*MillionSecond);
	st=KeDelayExecutionThread( KernelMode, FALSE, &DelayTime );
	return (NT_SUCCESS(st));
}
Beispiel #7
0
VOID
SoundMixerChangedItem(
    IN OUT PMIXER_INFO      MixerInfo,
    IN OUT PMIXER_DATA_ITEM MixerItem
)
{
    ASSERTMSG("Invalid mixer info!", MixerInfo->Key == MIX_INFO_KEY);

    /*
    **  There are 2 tasks :
    **
    **  1.  Increment the current 'logical' time
    **
    **  2.  Move the item to the head of the list and set its current time
    **
    **  3.  Notify all those waiting for notification
    */

    RemoveEntryList(&MixerItem->Entry);

    MixerInfo->CurrentLogicalTime =
        RtlLargeIntegerAdd(MixerInfo->CurrentLogicalTime,
                           RtlConvertLongToLargeInteger(1L));

    MixerItem->LastSet = MixerInfo->CurrentLogicalTime;

    InsertHeadList(&MixerInfo->ChangedItems, &MixerItem->Entry);

    /*
    **  Complete all notification Irps.
    */

    {
        KIRQL OldIrql;
        PIRP pIrp;

        while (TRUE) {

            pIrp = SoundRemoveFromCancellableQ(&MixerInfo->NotifyQueue);

            if (pIrp == NULL) {
                break;
            }

            SoundMixerNotify(pIrp, MixerInfo);
        }
    }
}
Beispiel #8
0
VOID
SoundInitDataItem(
    PMIXER_INFO         MixerInfo,
    PMIXER_DATA_ITEM    MixerDataItem,
    USHORT              Message,
    USHORT              Id
)
{
    ASSERTMSG("Mixer info not initialized!", MixerInfo->Key == MIX_INFO_KEY);

    MixerDataItem->LastSet = RtlConvertLongToLargeInteger(0L);

    MixerDataItem->Message = Message;
    MixerDataItem->Id      = Id;
    InsertTailList(&MixerInfo->ChangedItems, &MixerDataItem->Entry);
}
Beispiel #9
0
NTSTATUS DriverRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) 
{
	Debug("Enter DriverRead");
	
	IoMarkIrpPending(pIrp);

	MyDeviceExtend* tDevExtend = (MyDeviceExtend*)pDevObj->DeviceExtension;
	ULONG tTime = 3000000;
	tDevExtend->TimeCount = RtlConvertLongToLargeInteger(-10*tTime);
	tDevExtend->CurIrp	= pIrp;

	NTSTATUS tRetStatus;
	tRetStatus = KeSetTimer(&tDevExtend->Timer,tDevExtend->TimeCount,&tDevExtend->DPC);

	Debug("Leave DriverRead");
	return STATUS_PENDING;
}
Beispiel #10
0
NTSTATUS
NTAPI
Connect(
	__in PWSK_SOCKET	WskSocket,
	__in PSOCKADDR		RemoteAddress
)
{
	KEVENT		CompletionEvent = { 0 };
	PIRP		Irp = NULL;
	NTSTATUS	Status = STATUS_UNSUCCESSFUL;

	if (g_SocketsState != INITIALIZED || !WskSocket || !RemoteAddress)
		return STATUS_INVALID_PARAMETER;

	Status = InitWskData(&Irp, &CompletionEvent);
	if (!NT_SUCCESS(Status)) {
		return Status;
	}

	Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskConnect(
		WskSocket,
		RemoteAddress,
		0,
		Irp);

	if (Status == STATUS_PENDING) {
		LARGE_INTEGER	nWaitTime;
		nWaitTime = RtlConvertLongToLargeInteger(-1 * 1000 * 1000 * 10);
		if ((Status = KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, &nWaitTime)) == STATUS_TIMEOUT)
		{
			IoCancelIrp(Irp);
			KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
		}
	}

	if (Status == STATUS_SUCCESS)
	{
		Status = Irp->IoStatus.Status;
	}

	IoFreeIrp(Irp);
	return Status;
}
VOID KBFDriverUnload(IN PDRIVER_OBJECT aDriverObject)
{
    PAGED_CODE();

    PDEVICE_OBJECT deviceObject = NULL;
    PDEVICE_OBJECT oldDeviceObject = NULL;
    PDEVICE_EXTENSION deviceExtension = NULL;

    LARGE_INTEGER lDelay;
    PRKTHREAD currentThread = NULL;

    if (g_filterStart == TRUE)
    {
        // delay some time
        lDelay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND);
        currentThread = KeGetCurrentThread();

        // 将当前线程设置为低实时模式,以便让它的运行尽量少影响其他程序
        KeSetPriorityThread(currentThread, LOW_REALTIME_PRIORITY);

        UNREFERENCED_PARAMETER(aDriverObject);
        DbgPrint("wykbflt.sys : DriverEntry unloading .\n");

        // 遍历所有设备并一律解除绑定
        deviceObject = aDriverObject->DeviceObject;
        while (deviceObject)
        {
            KBFDetach(deviceObject);
            deviceObject = deviceObject->NextDevice;
        }

        ASSERT(NULL == aDriverObject->DeviceObject);

        while (gC2pKeyCount)
        {
            KeDelayExecutionThread(KernelMode, FALSE, &lDelay);
        }
    }

    DbgPrint("wykbflt.sys : DriverEntry unload ok .\n");
    return ;
}
Beispiel #12
0
static void set_timer(unsigned long delta)
{
	if (delta == LKL_TIMER_INIT)
		return;

	if (delta == LKL_TIMER_SHUTDOWN) {
		/* should not deliver timer shutdown twice */
		if(timer_done) {
			DbgPrint("*** LKL_TIMER_SHUTDOWN called when timer_done ***");
			while(1)
				;
		}

		/* deque the timer so it won't be put in signaled state */
		KeCancelTimer(&timer);
		/* timers run on DPCs. This returns after all active
		 * DPCs have executed, which means the timer is
		 * certainly not running nor being schduled after this
		 * point. */
		KeFlushQueuedDpcs();


		/* signal the timer interrupt we're done */
		timer_done = 1;
		/* the memory barrier is needed because it may be
		 * possible for the compiler/cpu to call
		 * KeReleaseSemaphore before assigning
		 * timer_done. That would make the timer_thread wake
		 * from the wait-for-multiple-objs without noticing
		 * out signalling */
		KeMemoryBarrier();
		KeReleaseSemaphore(&timer_killer_sem, 0, 1, 0);
		return;
	}

	KeSetTimer(&timer, RtlConvertLongToLargeInteger((unsigned long)(-(delta/100))), NULL);
}
Beispiel #13
0
NTSTATUS
SpxTimerInit(
    VOID
)
/*++

Routine Description:

 	Initialize the timer component for the appletalk stack.

Arguments:


Return Value:


--*/
{
#if      !defined(_PNP_POWER)
    BOOLEAN	TimerStarted;
#endif  !_PNP_POWER

    // Initialize the timer and its associated Dpc. timer will be kicked
    // off when we get the first card arrival notification from ipx
    KeInitializeTimer(&spxTimer);
    CTEInitLock(&spxTimerLock);
    KeInitializeDpc(&spxTimerDpc, spxTimerDpcRoutine, NULL);
    spxTimerTick = RtlConvertLongToLargeInteger(SPX_TIMER_TICK);
#if      !defined(_PNP_POWER)
    TimerStarted = KeSetTimer(&spxTimer,
                              spxTimerTick,
                              &spxTimerDpc);
    CTEAssert(!TimerStarted);
#endif  !_PNP_POWER
    return STATUS_SUCCESS;
}
Beispiel #14
0
dStatus kdi_GetFloppyController
(
/* INPUT PARAMETERS:  */

	KdiContextPtr kdi_context

/* UPDATE PARAMETERS: */

/* OUTPUT PARAMETERS: */

)
/* COMMENTS: *****************************************************************
 *
 * DEFINITIONS: *************************************************************/
{

/* DATA: ********************************************************************/

	dSDDWord controller_wait;
	NTSTATUS wait_status;

/* CODE: ********************************************************************/

	if (!kdi_context->own_floppy_event) {

		controller_wait = RtlLargeIntegerNegate(
                  		RtlConvertLongToLargeInteger(
                  		(LONG)(10 * 1000 * 15000)
                  		)
                  		);

		wait_status = STATUS_SUCCESS;

		kdi_CheckedDump(
			QIC117INFO,
			"Q117i: Waiting Controller Event\n", 0l);

        if (kdi_context->controller_data.floppyEnablerApiSupported) {

            wait_status = kdi_FloppyEnabler(
                            kdi_context->controller_data.apiDeviceObject,
                            IOCTL_AQUIRE_FDC,
                            &controller_wait);

        } else {

            wait_status = KeWaitForSingleObject(
                                kdi_context->controller_event,
                                Executive,
                                KernelMode,
                                dFALSE,
                                &controller_wait);
        }

        if (wait_status == STATUS_TIMEOUT) {

            kdi_CheckedDump(
                QIC117INFO,
                "Q117i: Timeout Controller Event\n", 0l);

            kdi_context->current_interrupt = dFALSE;
            kdi_context->own_floppy_event = dFALSE;
            return kdi_Error( ERR_KDI_CONTROLLER_BUSY, FCT_ID, ERR_SEQ_1 );

        } else {

            kdi_context->current_interrupt = dTRUE;
            kdi_context->own_floppy_event = dTRUE;

            kdi_CheckedDump(
                QIC117INFO,
                "Q117i: Have Controller Event\n", 0l);

            return kdi_Error( ERR_KDI_CLAIMED_CONTROLLER, FCT_ID, ERR_SEQ_1 );

        }

	}

	return DONT_PANIC;
}
Beispiel #15
0
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
								 IN PIRP pIrp) 
{
	KdPrint(("DriverB:Enter B HelloDDKRead\n"));
	NTSTATUS ntStatus = STATUS_SUCCESS;

	UNICODE_STRING DeviceName;
	RtlInitUnicodeString( &DeviceName, L"\\Device\\MyDDKDeviceA" );

	PDEVICE_OBJECT DeviceObject = NULL;
	PFILE_OBJECT FileObject = NULL;
	//得到设备对象指针
	ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject);

	KdPrint(("DriverB:FileObject:%x\n",FileObject));
	KdPrint(("DriverB:DeviceObject:%x\n",DeviceObject));

	if (!NT_SUCCESS(ntStatus))
	{
		KdPrint(("DriverB:IoGetDeviceObjectPointer() 0x%x\n", ntStatus ));

		ntStatus = STATUS_UNSUCCESSFUL;
		// 完成IRP
		pIrp->IoStatus.Status = ntStatus;
		pIrp->IoStatus.Information = 0;	// bytes xfered
		IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		KdPrint(("DriverB:Leave B HelloDDKRead\n"));

		return ntStatus;
	}

	KEVENT event;
	KeInitializeEvent(&event,NotificationEvent,FALSE);
	IO_STATUS_BLOCK status_block;
	LARGE_INTEGER offsert = RtlConvertLongToLargeInteger(0);

	//创建异步IRP
	PIRP pNewIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,
												DeviceObject,
												NULL,0,
												&offsert,&status_block);
	KdPrint(("pNewIrp->UserEvent :%x\n",pNewIrp->UserEvent));
	//设置pNewIrp->UserEvent,这样在IRP完成后可以通知该事件
	pNewIrp->UserEvent = &event;
	
 	KdPrint(("DriverB:pNewIrp:%x\n",pNewIrp));

	PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(pNewIrp);
	stack->FileObject = FileObject;

	NTSTATUS status = IoCallDriver(DeviceObject,pNewIrp);

    if (status == STATUS_PENDING) {
       status = KeWaitForSingleObject(
                            &event,
                            Executive,
                            KernelMode,
                            FALSE, // Not alertable
                            NULL);
        status = status_block.Status;
    }

	ZwClose(FileObject);
 
	//关闭设备句柄
 	ObDereferenceObject( FileObject );

	ntStatus = STATUS_SUCCESS;
	// 完成IRP
	pIrp->IoStatus.Status = ntStatus;
	pIrp->IoStatus.Information = 0;	// bytes xfered
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
	KdPrint(("DriverB:Leave B HelloDDKRead\n"));
	return ntStatus;
}
Beispiel #16
0
LONG NTAPI Receive(
	__in  PWSK_SOCKET	WskSocket,
	__out PVOID			Buffer,
	__in  ULONG			BufferSize,
	__in  ULONG			Flags,
	__in ULONG			Timeout
)
{
	KEVENT		CompletionEvent = { 0 };
	PIRP		Irp = NULL;
	WSK_BUF		WskBuffer = { 0 };
	LONG		BytesReceived = SOCKET_ERROR;
	NTSTATUS	Status = STATUS_UNSUCCESSFUL;

    struct      task_struct *thread = current;
    PVOID       waitObjects[2];
    int         wObjCount = 1;

	if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !BufferSize)
		return SOCKET_ERROR;

	if ((int) BufferSize <= 0)
	{
		return SOCKET_ERROR;
	}

	Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
	if (!NT_SUCCESS(Status)) {
		return SOCKET_ERROR;
	}

	Status = InitWskData(&Irp, &CompletionEvent);

	if (!NT_SUCCESS(Status)) {
		FreeWskBuffer(&WskBuffer);
		return SOCKET_ERROR;
	}

	Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskReceive(
				WskSocket,
				&WskBuffer,
				Flags,
				Irp);

    if (Status == STATUS_PENDING)
    {
        LARGE_INTEGER	nWaitTime;
        LARGE_INTEGER	*pTime;

        if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT)
        {
            pTime = 0;
        }
        else
        {
            nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10);
            pTime = &nWaitTime;
        }

        waitObjects[0] = (PVOID) &CompletionEvent;
        if (thread->has_sig_event)
        {
            waitObjects[1] = (PVOID) &thread->sig_event;
            wObjCount = 2;
        }
        Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL);
        switch (Status)
        {
        case STATUS_WAIT_0: // waitObjects[0] CompletionEvent
            if (Irp->IoStatus.Status == STATUS_SUCCESS)
            {
                BytesReceived = (LONG) Irp->IoStatus.Information;
            }
            else
            {
#ifdef _WIN32_LOGLINK 
                DbgPrint("RECV(%s) wsk(0x%p) multiWait err(0x%x:%s)\n", thread->comm, WskSocket, Irp->IoStatus.Status, GetSockErrorString(Irp->IoStatus.Status));
#else
				WDRBD_INFO("RECV(%s) wsk(0x%p) multiWait err(0x%x:%s)\n", thread->comm, WskSocket, Irp->IoStatus.Status, GetSockErrorString(Irp->IoStatus.Status));
#endif
				if(Irp->IoStatus.Status)
                {
                    BytesReceived = -ECONNRESET;
                }
            }
            break;

        case STATUS_WAIT_1:
            BytesReceived = -EINTR;
            break;

        case STATUS_TIMEOUT:
            BytesReceived = -EAGAIN;
            break;

        default:
            BytesReceived = SOCKET_ERROR;
            break;
        }
    }
	else
	{
		if (Status == STATUS_SUCCESS)
		{
			BytesReceived = (LONG) Irp->IoStatus.Information;
#ifdef _WIN32_LOGLINK
			DbgPrint("(%s) Rx No pending and data(%d) is avail\n", current->comm, BytesReceived);
#else
			WDRBD_INFO("(%s) Rx No pending and data(%d) is avail\n", current->comm, BytesReceived);
#endif
		}
		else
		{
#ifdef _WIN32_LOGLINK
			DbgPrint("WskReceive Error Status=0x%x\n", Status); // EVENT_LOG!
#else
			WDRBD_TRACE("WskReceive Error Status=0x%x\n", Status); // EVENT_LOG!
#endif
		}
	}

	if (BytesReceived == -EINTR || BytesReceived == -EAGAIN)
	{
		// cancel irp in wsk subsystem
		IoCancelIrp(Irp);
		KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
		if (Irp->IoStatus.Information > 0)
		{
			//WDRBD_INFO("rx canceled but rx data(%d) avaliable.\n", Irp->IoStatus.Information);
			BytesReceived = Irp->IoStatus.Information;
		}
	}

	IoFreeIrp(Irp);
	FreeWskBuffer(&WskBuffer);

	return BytesReceived;
}
Beispiel #17
0
LONG
NTAPI
SendLocal(
	__in PWSK_SOCKET	WskSocket,
	__in PVOID			Buffer,
	__in ULONG			BufferSize,
	__in ULONG			Flags,
	__in ULONG			Timeout
)
{
	KEVENT		CompletionEvent = { 0 };
	PIRP		Irp = NULL;
	WSK_BUF		WskBuffer = { 0 };
	LONG		BytesSent = SOCKET_ERROR;
	NTSTATUS	Status = STATUS_UNSUCCESSFUL;

	if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || ((int) BufferSize <= 0))
		return SOCKET_ERROR;

	Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
	if (!NT_SUCCESS(Status)) {
		return SOCKET_ERROR;
	}

	Status = InitWskData(&Irp, &CompletionEvent);
	if (!NT_SUCCESS(Status)) {
		FreeWskBuffer(&WskBuffer);
		return SOCKET_ERROR;
	}

	Flags |= WSK_FLAG_NODELAY;

	Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskSend(
		WskSocket,
		&WskBuffer,
		Flags,
		Irp);

	if (Status == STATUS_PENDING)
	{
		LARGE_INTEGER	nWaitTime;
		LARGE_INTEGER	*pTime;

		if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT)
		{
			pTime = NULL;
		}
		else
		{
			nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10);
			pTime = &nWaitTime;
		}
		Status = KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, pTime);

		switch (Status)
		{
		case STATUS_TIMEOUT:
			IoCancelIrp(Irp);
			KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
			BytesSent = -EAGAIN;
			break;

		case STATUS_WAIT_0:
			if (NT_SUCCESS(Irp->IoStatus.Status))
			{
				BytesSent = (LONG) Irp->IoStatus.Information;
			}
			else
			{
#ifdef _WIN32_LOGLINK
				DbgPrint("(%s) sent error(%s)\n", current->comm, GetSockErrorString(Irp->IoStatus.Status));
#else
				WDRBD_WARN("(%s) sent error(%s)\n", current->comm, GetSockErrorString(Irp->IoStatus.Status));
#endif
				switch (Irp->IoStatus.Status)
				{
				case STATUS_IO_TIMEOUT:
					BytesSent = -EAGAIN;
					break;
				case STATUS_INVALID_DEVICE_STATE:
					BytesSent = -EAGAIN;
					break;
				default:
					BytesSent = -ECONNRESET;
					break;
				}
			}
			break;

		default:
#ifdef _WIN32_LOGLINK
			DbgPrint("KeWaitForSingleObject failed. status 0x%x\n", Status);
#else
			WDRBD_ERROR("KeWaitForSingleObject failed. status 0x%x\n", Status);
#endif
			BytesSent = SOCKET_ERROR;
		}
	}
	else
	{
		if (Status == STATUS_SUCCESS)
		{
			BytesSent = (LONG) Irp->IoStatus.Information;
#ifdef _WIN32_LOGLINK
			DbgPrint("(%s) WskSend No pending: but sent(%d)!\n", current->comm, BytesSent);
#else
			WDRBD_WARN("(%s) WskSend No pending: but sent(%d)!\n", current->comm, BytesSent);
#endif
		}
		else
		{
#ifdef _WIN32_LOGLINK
			DbgPrint("(%s) WskSend error(0x%x)\n", current->comm, Status);
#else
			WDRBD_WARN("(%s) WskSend error(0x%x)\n", current->comm, Status);
#endif
			BytesSent = SOCKET_ERROR;
		}
	}

	IoFreeIrp(Irp);
	FreeWskBuffer(&WskBuffer);

	return BytesSent;
}
Beispiel #18
0
LONG
NTAPI
Send(
	__in PWSK_SOCKET	WskSocket,
	__in PVOID			Buffer,
	__in ULONG			BufferSize,
	__in ULONG			Flags,
	__in ULONG			Timeout,
	__in KEVENT			*send_buf_kill_event,
	__in struct			drbd_transport *transport,
	__in enum			drbd_stream stream
)
{
	KEVENT		CompletionEvent = { 0 };
	PIRP		Irp = NULL;
	WSK_BUF		WskBuffer = { 0 };
	LONG		BytesSent = SOCKET_ERROR; // DRBC_CHECK_WSK: SOCKET_ERROR be mixed EINVAL?
	NTSTATUS	Status = STATUS_UNSUCCESSFUL;

	if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || ((int) BufferSize <= 0))
		return SOCKET_ERROR;

	Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
	if (!NT_SUCCESS(Status)) {
		return SOCKET_ERROR;
	}

	Status = InitWskData(&Irp, &CompletionEvent);
	if (!NT_SUCCESS(Status)) {
		FreeWskBuffer(&WskBuffer);
		return SOCKET_ERROR;
	}

	Flags |= WSK_FLAG_NODELAY;

	Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskSend(
		WskSocket,
		&WskBuffer,
		Flags,
		Irp);

	if (Status == STATUS_PENDING)
	{
		LARGE_INTEGER	nWaitTime;
		LARGE_INTEGER	*pTime;

		int retry_count = 0;
	retry:
		if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT)
		{
			pTime = NULL;
		}
		else
		{
			nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10);
			pTime = &nWaitTime;
		}
		{
			struct      task_struct *thread = current;
			PVOID       waitObjects[2];
			int         wObjCount = 1;

			waitObjects[0] = (PVOID) &CompletionEvent;
#ifndef _WIN32_SEND_BUFFING 
			// in send-buffering, Netlink , call_usermodehelper are distinguished to SendLocal
			// KILL event is only used in send-buffering thread while send block. 
			// WIN32_V9_REFACTO_:required to refactoring that input param, log message are simplized.
#else

#endif
			Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL);
			switch (Status)
			{
			case STATUS_TIMEOUT:
#ifdef _WIN32_SEND_BUFFING
				if (wObjCount == 1)
				{
					retry_count++;
					WDRBD_WARN("(%s) sent timeout=%d sz=%d retry_count=%d WskSocket=%p IRP=%p\n",
						current->comm, Timeout, BufferSize, retry_count,WskSocket, Irp);

					// required to refactroing about retrying method.

					goto retry;
				}
#endif
				if (transport != NULL)
				{
					if (!drbd_stream_send_timed_out(transport, stream))
					{
						goto retry;
					}
				}

				IoCancelIrp(Irp);
				KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
				BytesSent = -EAGAIN;
				break;

			case STATUS_WAIT_0:
				if (NT_SUCCESS(Irp->IoStatus.Status))
				{
					BytesSent = (LONG)Irp->IoStatus.Information;
				}
				else
				{
					WDRBD_WARN("tx error(%s) wsk(0x%p)\n", GetSockErrorString(Irp->IoStatus.Status), WskSocket);
					switch (Irp->IoStatus.Status)
					{
						case STATUS_IO_TIMEOUT:
							BytesSent = -EAGAIN;
							break;
						case STATUS_INVALID_DEVICE_STATE:
							BytesSent = -EAGAIN;
							break;
						default:
							BytesSent = -ECONNRESET;
							break;
					}
				}
				break;

			//case STATUS_WAIT_1: // common: sender or send_bufferinf thread's kill signal
			//	IoCancelIrp(Irp);
			//	KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
			//	BytesSent = -EINTR;
			//	break;

			default:
				WDRBD_ERROR("Wait failed. status 0x%x\n", Status);
				BytesSent = SOCKET_ERROR;
			}
		}
	}
	else
	{
		if (Status == STATUS_SUCCESS)
		{
			BytesSent = (LONG) Irp->IoStatus.Information;
			WDRBD_WARN("(%s) WskSend No pending: but sent(%d)!\n", current->comm, BytesSent);
		}
		else
		{
			WDRBD_WARN("(%s) WskSend error(0x%x)\n", current->comm, Status);
			BytesSent = SOCKET_ERROR;
		}
	}

	IoFreeIrp(Irp);
	FreeWskBuffer(&WskBuffer);

	return BytesSent;
}
Beispiel #19
0
PWSK_SOCKET
NTAPI
Accept(
	__in PWSK_SOCKET	WskSocket,
	__out_opt PSOCKADDR	LocalAddress,
	__out_opt PSOCKADDR	RemoteAddress,
	__out_opt NTSTATUS	*RetStaus,
	__in int			timeout
)
{
	KEVENT			CompletionEvent = { 0 };
	PIRP			Irp = NULL;
	NTSTATUS		Status = STATUS_UNSUCCESSFUL;
	PWSK_SOCKET		AcceptedSocket = NULL;
    struct task_struct *thread = current;
    PVOID waitObjects[2];
    int wObjCount = 1;

	if (g_SocketsState != INITIALIZED || !WskSocket)
	{
		*RetStaus = SOCKET_ERROR;
		return NULL;
	}

	Status = InitWskData(&Irp, &CompletionEvent);
	if (!NT_SUCCESS(Status)) {
		*RetStaus = Status;
		return NULL;
	}

	Status = ((PWSK_PROVIDER_LISTEN_DISPATCH) WskSocket->Dispatch)->WskAccept(
		WskSocket,
		0,
		NULL,
		NULL,
		LocalAddress,
		RemoteAddress,
		Irp);

	if (Status == STATUS_PENDING)
	{
		LARGE_INTEGER	nWaitTime;
		LARGE_INTEGER	*pTime;

		if (timeout <= 0 || timeout == MAX_SCHEDULE_TIMEOUT)
		{
			pTime = 0;
		}
		else
		{
			nWaitTime = RtlConvertLongToLargeInteger(-1 * timeout * 10000000);
			pTime = &nWaitTime;
		}

        waitObjects[0] = (PVOID) &CompletionEvent;
        if (thread->has_sig_event)
        {
            waitObjects[1] = (PVOID) &thread->sig_event;
            wObjCount = 2;
        }

        Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL);

		switch (Status)
		{
			case STATUS_WAIT_0:
				break;

			case STATUS_WAIT_0 + 1:
				IoCancelIrp(Irp);
				KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
				*RetStaus = -EINTR;	
				break;

			case STATUS_TIMEOUT:
				IoCancelIrp(Irp);
				KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
				*RetStaus = STATUS_TIMEOUT;
				break;

			default:
				WDRBD_ERROR("Unexpected Error Status=0x%x\n", Status);
				break;
		}
	}
	else
	{
		if (Status != STATUS_SUCCESS)
		{
			WDRBD_TRACE("Accept Error Status=0x%x\n", Status);
		}
	}

	AcceptedSocket = (Status == STATUS_SUCCESS) ? (PWSK_SOCKET) Irp->IoStatus.Information : NULL;
	IoFreeIrp(Irp);
	return AcceptedSocket;
}
Beispiel #20
0
void
initialize (void)
{

    ULONG SidWithZeroSubAuthorities;
    ULONG SidWithOneSubAuthority;
    ULONG SidWithThreeSubAuthorities;
    ULONG SidWithFourSubAuthorities;

    SID_IDENTIFIER_AUTHORITY NullSidAuthority    = SECURITY_NULL_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY WorldSidAuthority   = SECURITY_WORLD_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY LocalSidAuthority   = SECURITY_LOCAL_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;

    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;


    //
    //  The following SID sizes need to be allocated
    //

    SidWithZeroSubAuthorities  = GetSidLengthRequired( 0 );
    SidWithOneSubAuthority     = GetSidLengthRequired( 1 );
    SidWithThreeSubAuthorities = GetSidLengthRequired( 3 );
    SidWithFourSubAuthorities  = GetSidLengthRequired( 4 );

    //
    //  Allocate and initialize the universal SIDs
    //

    NullSid         = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority);
    WorldSid        = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority);
    LocalSid        = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority);
    CreatorOwnerSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority);

    InitializeSid( NullSid,    &NullSidAuthority, 1 );
    InitializeSid( WorldSid,   &WorldSidAuthority, 1 );
    InitializeSid( LocalSid,   &LocalSidAuthority, 1 );
    InitializeSid( CreatorOwnerSid, &CreatorSidAuthority, 1 );

    *(GetSidSubAuthority( NullSid, 0 ))         = SECURITY_NULL_RID;
    *(GetSidSubAuthority( WorldSid, 0 ))        = SECURITY_WORLD_RID;
    *(GetSidSubAuthority( LocalSid, 0 ))        = SECURITY_LOCAL_RID;
    *(GetSidSubAuthority( CreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID;

    //
    // Allocate and initialize the NT defined SIDs
    //

    NtAuthoritySid  = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithZeroSubAuthorities);
    DialupSid       = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority);
    NetworkSid      = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority);
    BatchSid        = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority);
    InteractiveSid  = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority);
    LocalSystemSid  = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority);

    InitializeSid( NtAuthoritySid,   &NtAuthority, 0 );
    InitializeSid( DialupSid,        &NtAuthority, 1 );
    InitializeSid( NetworkSid,       &NtAuthority, 1 );
    InitializeSid( BatchSid,         &NtAuthority, 1 );
    InitializeSid( InteractiveSid,   &NtAuthority, 1 );
    InitializeSid( LocalSystemSid,   &NtAuthority, 1 );

    *(GetSidSubAuthority( DialupSid,       0 )) = SECURITY_DIALUP_RID;
    *(GetSidSubAuthority( NetworkSid,      0 )) = SECURITY_NETWORK_RID;
    *(GetSidSubAuthority( BatchSid,        0 )) = SECURITY_BATCH_RID;
    *(GetSidSubAuthority( InteractiveSid,  0 )) = SECURITY_INTERACTIVE_RID;
    *(GetSidSubAuthority( LocalSystemSid,  0 )) = SECURITY_LOCAL_SYSTEM_RID;


    //
    // Initialize the well known privilege values
    //

    SeCreateTokenPrivilege =
        RtlConvertLongToLargeInteger(SE_CREATE_TOKEN_PRIVILEGE);
    SeAssignPrimaryTokenPrivilege =
        RtlConvertLongToLargeInteger(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE);
    SeLockMemoryPrivilege =
        RtlConvertLongToLargeInteger(SE_LOCK_MEMORY_PRIVILEGE);
    SeIncreaseQuotaPrivilege =
        RtlConvertLongToLargeInteger(SE_INCREASE_QUOTA_PRIVILEGE);
    SeUnsolicitedInputPrivilege =
        RtlConvertLongToLargeInteger(SE_UNSOLICITED_INPUT_PRIVILEGE);
    SeTcbPrivilege =
        RtlConvertLongToLargeInteger(SE_TCB_PRIVILEGE);
    SeSecurityPrivilege =
        RtlConvertLongToLargeInteger(SE_SECURITY_PRIVILEGE);
    SeTakeOwnershipPrivilege =
        RtlConvertLongToLargeInteger(SE_TAKE_OWNERSHIP_PRIVILEGE);
    SeLoadDriverPrivilege =
        RtlConvertLongToLargeInteger(SE_LOAD_DRIVER_PRIVILEGE);
    SeCreatePagefilePrivilege =
        RtlConvertLongToLargeInteger(SE_CREATE_PAGEFILE_PRIVILEGE);
    SeIncreaseBasePriorityPrivilege =
        RtlConvertLongToLargeInteger(SE_INC_BASE_PRIORITY_PRIVILEGE);
    SeSystemProfilePrivilege =
        RtlConvertLongToLargeInteger(SE_SYSTEM_PROFILE_PRIVILEGE);
    SeSystemtimePrivilege =
        RtlConvertLongToLargeInteger(SE_SYSTEMTIME_PRIVILEGE);
    SeProfileSingleProcessPrivilege =
        RtlConvertLongToLargeInteger(SE_PROF_SINGLE_PROCESS_PRIVILEGE);
    SeCreatePermanentPrivilege =
        RtlConvertLongToLargeInteger(SE_CREATE_PERMANENT_PRIVILEGE);
    SeBackupPrivilege =
        RtlConvertLongToLargeInteger(SE_BACKUP_PRIVILEGE);
    SeRestorePrivilege =
        RtlConvertLongToLargeInteger(SE_RESTORE_PRIVILEGE);
    SeShutdownPrivilege =
        RtlConvertLongToLargeInteger(SE_SHUTDOWN_PRIVILEGE);
    SeDebugPrivilege =
        RtlConvertLongToLargeInteger(SE_DEBUG_PRIVILEGE);
    SeAuditPrivilege =
        RtlConvertLongToLargeInteger(SE_AUDIT_PRIVILEGE);
    SeSystemEnvironmentPrivilege =
        RtlConvertLongToLargeInteger(SE_SYSTEM_ENVIRONMENT_PRIVILEGE);
    SeChangeNotifyPrivilege =
        RtlConvertLongToLargeInteger(SE_CHANGE_NOTIFY_PRIVILEGE);
    SeRemoteShutdownPrivilege =
        RtlConvertLongToLargeInteger(SE_REMOTE_SHUTDOWN_PRIVILEGE);


}
Beispiel #21
0
int
WSPAPI
WSPSendDisconnect (
    SOCKET Handle,
    LPWSABUF lpOutboundDisconnectData,
    LPINT lpErrno
    )

/*++

Routine Description:

    This routine is used on connection-oriented sockets to disable
    transmission, and to initiate termination of the connection along with the
    transmission of disconnect data, if any.

    After this routine has been successfully issued, subsequent sends are
    disallowed.

    lpOutboundDisconnectData, if not NULL, points to a buffer containing the
    outgoing disconnect data to be sent to the remote party.

    Note that WSPSendDisconnect() does not close the socket, and resources
    attached to the socket will not be freed until WSPCloseSocket() is invoked.

    WSPSendDisconnect() does not block regardless of the SO_LINGER setting on
    the socket.

    A WinSock SPI client should not rely on being able to re-use a socket after
    it has been WSPSendDisconnect()ed. In particular, a WinSock provider is not
    required to support the use of WSPConnect() on such a socket.

Arguments:

    s - A descriptor identifying a socket.

    lpOutboundDisconnectData - A pointer to the outgoing disconnect data.

    lpErrno - A pointer to the error code.

Return Value:

    If no error occurs, WSPSendDisconnect() returns 0. Otherwise, a value of
        SOCKET_ERROR is returned, and a specific error code is available in
        lpErrno.

--*/

{

    NTSTATUS status;
	PWINSOCK_TLS_DATA	tlsData;
    PSOCKET_INFORMATION socket;
    IO_STATUS_BLOCK ioStatusBlock;
    int err;
    AFD_PARTIAL_DISCONNECT_INFO disconnectInfo;

    WS_ENTER( "WSPSendDisconnect", (PVOID)Handle, (PVOID)lpOutboundDisconnectData, NULL, NULL );

    WS_ASSERT( lpErrno != NULL );

    err = SockEnterApi( &tlsData );

    if( err != NO_ERROR ) {

        WS_EXIT( "WSPSendDisconnect", SOCKET_ERROR, TRUE );
        *lpErrno = err;
        return SOCKET_ERROR;

    }

    //
    // Set up locals so that we know how to clean up on exit.
    //

    socket = NULL;

    //
    // Find a pointer to the socket structure corresponding to the
    // passed-in handle.
    //

    socket = SockFindAndReferenceSocket( Handle, TRUE );

    if ( socket == NULL ) {

        err = WSAENOTSOCK;
        goto exit;

    }

    //
    // Acquire the lock that protect this socket.
    //

    SockAcquireSocketLockExclusive( socket );

    //
    // If this is not a datagram socket, then it must be connected in order
    // for WSPSendDisconnect() to be a legal operation.
    //

    if ( !IS_DGRAM_SOCK(socket) &&
             !SockIsSocketConnected( socket ) ) {

        err = WSAENOTCONN;
        goto exit;

    }

#ifdef _AFD_SAN_SWITCH_
	//
	// Handle SAN disconnect first
	//
	if (SockSanEnabled && socket->SanSocket &&
		socket->SanSocket->IsConnected == CONNECTED) {

		socket->SendShutdown = TRUE;

		SockSanShutdown(socket, SD_SEND);

		goto exit;
	}
#endif //_AFD_SAN_SWITCH_

    //
    // Setup the disconnect info.
    //

    disconnectInfo.DisconnectMode = AFD_PARTIAL_DISCONNECT_SEND;
    disconnectInfo.Timeout = RtlConvertLongToLargeInteger( -1 );

    // !!! temporary HACK for tp4!

    if( socket->AddressFamily == AF_OSI ) {

        disconnectInfo.DisconnectMode = AFD_ABORTIVE_DISCONNECT;

    }

    __try {
        if( lpOutboundDisconnectData != NULL &&
            lpOutboundDisconnectData->buf != NULL &&
            lpOutboundDisconnectData->len > 0 ) {

            INT bufferLength;

            //
            // Set the disconnect data on the socket.
            //

            bufferLength = (INT)lpOutboundDisconnectData->len;

            err = SockSetConnectData(
                      socket,
                      IOCTL_AFD_SET_DISCONNECT_DATA,
                      (PCHAR)lpOutboundDisconnectData->buf,
                      bufferLength,
                      &bufferLength
                      );

            if( err != NO_ERROR ) {

                goto exit;

            }

        }
    }
    __except (SOCK_EXCEPTION_FILTER()) {
        err = WSAEFAULT;
        goto exit;
    }

    //
    // Note in the socket state that sends are shutdown.
    //

    socket->SendShutdown = TRUE;

    IF_DEBUG(SHUTDOWN) {

        WS_PRINT(( "starting WSPSendDisconnect for socket %lx\n", Handle ));

    }

    //
    // Send the IOCTL to AFD for processing.
    //

    status = NtDeviceIoControlFile(
                 socket->HContext.Handle,
                 tlsData->EventHandle,
                 NULL,                      // APC Routine
                 NULL,                      // APC Context
                 &ioStatusBlock,
                 IOCTL_AFD_PARTIAL_DISCONNECT,
                 &disconnectInfo,
                 sizeof(disconnectInfo),
                 NULL,                      // OutputBuffer
                 0L                         // OutputBufferLength
                 );

    if ( status == STATUS_PENDING ) {

        SockReleaseSocketLock( socket );
        SockWaitForSingleObject(
            tlsData->EventHandle,
            Handle,
            SOCK_NEVER_CALL_BLOCKING_HOOK,
            SOCK_NO_TIMEOUT
            );
        SockAcquireSocketLockExclusive( socket );
        status = ioStatusBlock.Status;

    }

    if ( !NT_SUCCESS(status) ) {

        err = SockNtStatusToSocketError( status );
        goto exit;

    }

    //
    // Notify the helper DLL that the socket has been shut down.
    //

    err = SockNotifyHelperDll( socket, WSH_NOTIFY_SHUTDOWN_SEND );

    if ( err != NO_ERROR ) {

        goto exit;

    }

exit:

    IF_DEBUG(SHUTDOWN) {

        if ( err != NO_ERROR ) {

            WS_PRINT(( "WSPSendDisconnect() on socket %lx (%lx) failed: %ld.\n",
                           Handle, socket, err ));

        } else {

            WS_PRINT(( "WSPSendDisconnect() on socket %lx (%lx) succeeded.\n",
                           Handle, socket ));

        }

    }

    if ( socket != NULL ) {

        SockReleaseSocketLock( socket );
        SockDereferenceSocket( socket );

    }

    if ( err != NO_ERROR ) {

        WS_EXIT( "WSPSendDisconnect", SOCKET_ERROR, TRUE );
        *lpErrno = err;
        return SOCKET_ERROR;

    }

    WS_EXIT( "WSPSendDisconnect", NO_ERROR, FALSE );
    return NO_ERROR;

}   // WSPSendDisconnect
Beispiel #22
0
static
_Check_return_
NTSTATUS
LcFetchFileByChunks (
    _In_  PCFLT_RELATED_OBJECTS FltObjects,
    _In_  HANDLE                SourceFileHandle,
    _In_  PLARGE_INTEGER        SourceFileSize,
    _Out_ PLARGE_INTEGER        BytesCopied
    )
/*++

Summary:

    This function copies the original file from the 'SourceFileHandle' to the currently opened
    file ('FltObjects->FileObject') by chunks.

    It maintains its own list of chunks, and extends it, if there are no chunks available to read into.
    Write operation goes from one chunk to another in a sequential order. If the next chunk is empty,
    write waits for the read to be completed, and proceeds.

    There are simple rules for chunks allocation:
    1. Up to two chunks are initially allocated:
       a) If the file is smaller than the 'ChunkSize', only one chunk is allocated with buffer
          that is equal to the file size.
       b) If the file is larger than the 'ChunkSize', two chunks are allocated, taking the
          file size into account for the second chunk size.
    2. If all chunks currently allocated are full and awaiting to be written to a disk, and
       the current amount of chunks is lesser than 'MaxChunks', an additional chunk is allocated.

    There is a corner case, when the actual file size differs from the reported one. In this case
    one of the chunks in the list will be smaller than the 'ChunkSize'.
    For example, 'MaxChunks' is 3, ChunkSize is '10', file size reported is '12', and actual file
    size is '25'.
    Two chunks will be initially allocated: [1] 10b; [2] (12-10)=2b.
    Later on, when all of them will be filled in with the data, and EOF will not be received,
    because the actual size is 25b, another chunk [3] of size 10b (ChunkSize) will be allocated.
    In total, there will be three chunks: 10b, 2b, and 10b.
    We don't reallocate the 2nd chunk, because this driver is supposed to be used with a proper
    filesystems, but making this modification might be a valuable TODO item.

    Let's look at how chunks work.
    All chunks are stored in the doubly-linked list. [Head] node doesn't contain any buffer to
    store data in. Refer to the 'FILE_CHUNK' structure for details.
    MSDN about lists: http://msdn.microsoft.com/en-us/library/windows/hardware/ff563802(v=vs.85).aspx

    For large files we will have two chunks from the beginning.
    [Head] <-> [1] <-> [2] <-> [Head]

    There are pointers for [R]ead and [W]rite.

    When the first chunk is being read, the list will look like the following:
    [Head] <-> [1] <-> [2] <-> [Head]
      [W]      [R]

    [W] is awaiting for the [1] to be filled in with the data before writing it to the disk.

    When the [1] chunk is filled with the data:
    [Head] <-> [1*] <-> [2] <-> [Head]
                [W]     [R]

    [1] is full and is being written to a disk, and we're reading into chunk [2].
    Let's also assume that the reads are faster then writes. When the [2] chunk is
    full, there are no free chunks available:
    [Head] <-> [1*] <-> [2*] <-> [Head]
                [W]      [R]

    If the current amount of chunks is lesser than the 'MaxChunks' value, a new chunk will be
    allocated before the next [R] node. In this case it will be added before [Head] to the end
    of the list, and read will continue:
    [Head] <-> [1*] <-> [2*] <-> [3] <-> [Head]
                [W]              [R]

    Then [W] and [R] finish, and [W] moves to the [2] chunk.
    [Head] <-> [1] <-> [2*] <-> [3*] <-> [Head]
                        [W]      [R]

    [R] sees that [1] chunk is available, and reads into it:
    [Head] <-> [1] <-> [2*] <-> [3*] <-> [Head]
               [R]      [W]

    After [R] finishes reading, there are no free chunks again:
    [Head] <-> [1*] <-> [2*] <-> [3*] <-> [Head]
               [R]       [W]

    A new chunk can be allocated again before the [2]:
    [Head] <-> [1*] <-> [4] <-> [2*] <-> [3*] <-> [Head]
                        [R]      [W]

    With this approach, [R] will fill chunks [1]->[2]->[3]->[1]->[4], and write will
    write them in the same order.
    I.e. allocating a new chunk before the next filled chunk (if the amount of chunks
    is lesser than the 'MaxChunks') makes sure that the data is written sequentially,
    and there is no need to constantly seek in the file.

Arguments:

    FltObjects       - Pointer to the 'FLT_RELATED_OBJECTS' data structure containing
                       opaque handles to this filter, instance, its associated volume and
                       file object.

    SourceFileHandle - Handle to the source file to copy content from.

    SourceFileSize   - Size of the source file.

    BytesCopied      - Pointer to the LARGE_INTEGER structure that receives the amount
                       of bytes copied.

Return Value:

    The return value is the status of the operation.

--*/
{
    NTSTATUS               status                = STATUS_SUCCESS;

    LIST_ENTRY             chunksListHead        = { 0 };
    ULONG                  chunkListLength       = 0;

    // State of the R/W operations.
    BOOLEAN                readComplete          = FALSE;
    BOOLEAN                writeComplete         = FALSE;
    PFILE_CHUNK            readChunk             = NULL;
    PFILE_CHUNK            writeChunk            = NULL;
    BOOLEAN                eof                   = FALSE;
    BOOLEAN                waitingForRead        = FALSE;
    KEVENT                 writeEvent            = { 0 };

    WRITE_CALLBACK_CONTEXT writeCallbackContext  = { 0 };

    LARGE_INTEGER          waitTimeout           = { 0 };
    LARGE_INTEGER          zeroTimeout           = { 0 };

    IO_STATUS_BLOCK        statusBlock           = { 0 };

    LARGE_INTEGER          remainingBytes        = { 0 };
    LARGE_INTEGER          totalBytesRead        = { 0 };
    LARGE_INTEGER          totalBytesWritten     = { 0 };
    LARGE_INTEGER          sourceFileOffset      = { 0 };
    LARGE_INTEGER          destinationFileOffset = { 0 };

    PAGED_CODE();

    FLT_ASSERT(FltObjects          != NULL);
    FLT_ASSERT(SourceFileHandle    != NULL);
    FLT_ASSERT(SourceFileSize      != NULL);
    FLT_ASSERT(SourceFileSize->QuadPart > 0);
    FLT_ASSERT(BytesCopied         != NULL);
    FLT_ASSERT(KeGetCurrentIrql()  == PASSIVE_LEVEL);

    *BytesCopied = RtlConvertLongToLargeInteger(0);

    __try
    {
        // Set the relative timeout (1 stands for 100 nanoseconds).
        waitTimeout           = RtlConvertLongToLargeInteger(-10000);
        waitTimeout.QuadPart *= TimeoutMilliseconds;

        KeInitializeEvent(&writeEvent, NotificationEvent, TRUE);
        writeCallbackContext.Event = &writeEvent;

        remainingBytes.QuadPart = SourceFileSize->QuadPart;

        NT_IF_FAIL_LEAVE(LcInitializeChunksList(FltObjects->Instance, &chunksListHead, remainingBytes, &chunkListLength));

        for (;;)
        {
            if (waitingForRead)
            {
                // Wait for the read operation to finish.
                NT_IF_FAIL_LEAVE(ZwWaitForSingleObject(SourceFileHandle, FALSE, &waitTimeout));
                readComplete = TRUE;
            }
            else
            {
                readComplete = ZwWaitForSingleObject(SourceFileHandle, FALSE, &zeroTimeout) == STATUS_SUCCESS;
            }

            writeComplete = KeReadStateEvent(&writeEvent) != 0;

            if (!eof && readComplete)
            {
                // If it's not the first read, update status of the current chunk.
                if (readChunk != NULL)
                {
                    status = statusBlock.Status;

                    if (NT_SUCCESS(status) || status == STATUS_END_OF_FILE)
                    {
                        ULONG bytesRead = (ULONG)statusBlock.Information;

                        readChunk->BytesInBuffer   = bytesRead;

                        remainingBytes.QuadPart   -= bytesRead;
                        totalBytesRead.QuadPart   += bytesRead;
                        sourceFileOffset.QuadPart += bytesRead;

                        if (status == STATUS_END_OF_FILE || bytesRead < readChunk->BufferSize)
                        {
                            eof    = TRUE;
                            status = STATUS_SUCCESS;

                            // Will not be used later in this case, only to have the proper data here.
                            remainingBytes.QuadPart = 0;
                        }
                    }

                    NT_IF_FAIL_LEAVE(status);
                }

                // Move to the next available chunk and schedule read.
                if (!eof)
                {
                    // If the remote file system returned an invalid file size, when we started reading it,
                    // this value might be negative. Set it to the default, so the newly allocated chunk
                    // will have the maximum allowed size.
                    if (remainingBytes.QuadPart <= 0)
                    {
                        remainingBytes.QuadPart = ChunkSize;
                    }

                    NT_IF_FAIL_LEAVE(LcGetNextAvailableChunk(
                        FltObjects->Instance,
                        &chunksListHead,
                        &readChunk,
                        &chunkListLength,
                        TRUE,              // Read operation.
                        &remainingBytes,
                        &writeEvent,
                        &waitTimeout));

                    // Schedule read operation for the current chunk.
                    status = ZwReadFile(
                        SourceFileHandle,
                        NULL,
                        NULL,
                        NULL,
                        &statusBlock,
                        readChunk->Buffer,
                        readChunk->BufferSize,
                        &sourceFileOffset,
                        NULL);

                    NT_IF_FALSE_LEAVE(status == STATUS_PENDING || status == STATUS_SUCCESS, status);
                }
            }

            if (writeComplete)
            {
                if (!waitingForRead)
                {
                    // If it's not the first write, update status of the current chunk.
                    if (writeChunk != NULL)
                    {
                        NT_IF_FAIL_LEAVE(writeCallbackContext.Status);

                        writeChunk->BytesInBuffer       = 0;
                        totalBytesWritten.QuadPart     += writeCallbackContext.BytesWritten;
                        destinationFileOffset.QuadPart += writeCallbackContext.BytesWritten;
                    }

                    NT_IF_FAIL_LEAVE(LcGetNextAvailableChunk(
                        FltObjects->Instance,
                        &chunksListHead,
                        &writeChunk,
                        &chunkListLength,
                        FALSE,             // Write operation.
                        NULL,
                        NULL,
                        NULL));
                }

                waitingForRead = FALSE;

                // If we don't have any data in the current chunk, restart from the beginning of the loop.
                if (writeChunk->BytesInBuffer == 0)
                {
                    if (eof)
                    {
                        // We're done!
                        break;
                    }
                    else
                    {
                        // Since we're waiting for the read to complete for the current chunk,
                        // don't change the chunk position on next iteration.
                        waitingForRead = TRUE;

                        continue;
                    }
                }

                KeClearEvent(&writeEvent);

                NT_IF_FAIL_LEAVE(FltWriteFile(
                    FltObjects->Instance,
                    FltObjects->FileObject,
                    &destinationFileOffset,
                    writeChunk->BytesInBuffer,
                    writeChunk->Buffer,
                    FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
                    NULL,
                    (PFLT_COMPLETED_ASYNC_IO_CALLBACK)&LcWriteCallback,
                    &writeCallbackContext));
            }
        }

        *BytesCopied = totalBytesWritten;
    }
    __finally
    {
        LcClearChunksList(FltObjects->Instance, &chunksListHead);
    }

    return status;
}
Beispiel #23
0
BOOLEAN
TSeVariableInitialization()
/*++

Routine Description:

    This function initializes the global variables used in security
    tests.

Arguments:

    None.

Return Value:

    TRUE if variables successfully initialized.
    FALSE if not successfully initialized.

--*/
{
    ULONG SidWithZeroSubAuthorities;
    ULONG SidWithOneSubAuthority;
    ULONG SidWithThreeSubAuthorities;
    ULONG SidWithFourSubAuthorities;

    SID_IDENTIFIER_AUTHORITY NullSidAuthority    = SECURITY_NULL_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY WorldSidAuthority   = SECURITY_WORLD_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY LocalSidAuthority   = SECURITY_LOCAL_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;

    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;


    SID_IDENTIFIER_AUTHORITY BedrockAuthority = BEDROCK_AUTHORITY;

    SID_IDENTIFIER_AUTHORITY BedrockAAuthority = BEDROCKA_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY BedrockBAuthority = BEDROCKB_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY BedrockCAuthority = BEDROCKC_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY BedrockDAuthority = BEDROCKD_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY BedrockEAuthority = BEDROCKE_AUTHORITY;

    //
    //  The following SID sizes need to be allocated
    //

    SidWithZeroSubAuthorities  = RtlLengthRequiredSid( 0 );
    SidWithOneSubAuthority     = RtlLengthRequiredSid( 1 );
    SidWithThreeSubAuthorities = RtlLengthRequiredSid( 3 );
    SidWithFourSubAuthorities  = RtlLengthRequiredSid( 4 );

    //
    //  Allocate and initialize the universal SIDs
    //

    NullSid    = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);
    WorldSid   = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);
    LocalSid   = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);
    CreatorOwnerSid = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);
    CreatorGroupSid = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);

    RtlInitializeSid( NullSid,    &NullSidAuthority, 1 );
    RtlInitializeSid( WorldSid,   &WorldSidAuthority, 1 );
    RtlInitializeSid( LocalSid,   &LocalSidAuthority, 1 );
    RtlInitializeSid( CreatorOwnerSid, &CreatorSidAuthority, 1 );
    RtlInitializeSid( CreatorGroupSid, &CreatorSidAuthority, 1 );

    *(RtlSubAuthoritySid( NullSid, 0 ))    = SECURITY_NULL_RID;
    *(RtlSubAuthoritySid( WorldSid, 0 ))   = SECURITY_WORLD_RID;
    *(RtlSubAuthoritySid( LocalSid, 0 ))   = SECURITY_LOCAL_RID;
    *(RtlSubAuthoritySid( CreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID;
    *(RtlSubAuthoritySid( CreatorGroupSid, 0 )) = SECURITY_CREATOR_GROUP_RID;

    //
    // Allocate and initialize the NT defined SIDs
    //

    NtAuthoritySid  = (PSID)TstAllocatePool(PagedPool,SidWithZeroSubAuthorities);
    DialupSid       = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);
    NetworkSid      = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);
    BatchSid        = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);
    InteractiveSid  = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);
    LocalSystemSid  = (PSID)TstAllocatePool(PagedPool,SidWithOneSubAuthority);

    RtlInitializeSid( NtAuthoritySid,   &NtAuthority, 0 );
    RtlInitializeSid( DialupSid,        &NtAuthority, 1 );
    RtlInitializeSid( NetworkSid,       &NtAuthority, 1 );
    RtlInitializeSid( BatchSid,         &NtAuthority, 1 );
    RtlInitializeSid( InteractiveSid,   &NtAuthority, 1 );
    RtlInitializeSid( LocalSystemSid,   &NtAuthority, 1 );

    *(RtlSubAuthoritySid( DialupSid,       0 )) = SECURITY_DIALUP_RID;
    *(RtlSubAuthoritySid( NetworkSid,      0 )) = SECURITY_NETWORK_RID;
    *(RtlSubAuthoritySid( BatchSid,        0 )) = SECURITY_BATCH_RID;
    *(RtlSubAuthoritySid( InteractiveSid,  0 )) = SECURITY_INTERACTIVE_RID;
    *(RtlSubAuthoritySid( LocalSystemSid,  0 )) = SECURITY_LOCAL_SYSTEM_RID;



    //
    // Allocate and initialize the Bedrock SIDs
    //

    BedrockDomainSid  = (PSID)TstAllocatePool(PagedPool,SidWithThreeSubAuthorities);
    BedrockADomainSid  = (PSID)TstAllocatePool(PagedPool,SidWithThreeSubAuthorities);
    BedrockBDomainSid  = (PSID)TstAllocatePool(PagedPool,SidWithThreeSubAuthorities);
    BedrockCDomainSid  = (PSID)TstAllocatePool(PagedPool,SidWithThreeSubAuthorities);
    BedrockDDomainSid  = (PSID)TstAllocatePool(PagedPool,SidWithThreeSubAuthorities);
    BedrockEDomainSid  = (PSID)TstAllocatePool(PagedPool,SidWithThreeSubAuthorities);

    FredSid           = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);
    WilmaSid          = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);
    PebblesSid        = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);
    DinoSid           = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);

    BarneySid         = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);
    BettySid          = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);
    BambamSid         = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);

    FlintstoneSid     = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);
    RubbleSid         = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);

    AdultSid          = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);
    ChildSid          = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);

    NeandertholSid    = (PSID)TstAllocatePool(PagedPool,SidWithFourSubAuthorities);

    RtlInitializeSid( BedrockDomainSid,   &BedrockAuthority, 3 );
    *(RtlSubAuthoritySid( BedrockDomainSid, 0)) = BEDROCK_SUBAUTHORITY_0;
    *(RtlSubAuthoritySid( BedrockDomainSid, 1)) = BEDROCK_SUBAUTHORITY_1;
    *(RtlSubAuthoritySid( BedrockDomainSid, 2)) = BEDROCK_SUBAUTHORITY_2;

    RtlInitializeSid( BedrockADomainSid,   &BedrockAAuthority, 3 );
    *(RtlSubAuthoritySid( BedrockADomainSid, 0)) = BEDROCKA_SUBAUTHORITY_0;
    *(RtlSubAuthoritySid( BedrockADomainSid, 1)) = BEDROCKA_SUBAUTHORITY_1;
    *(RtlSubAuthoritySid( BedrockADomainSid, 2)) = BEDROCKA_SUBAUTHORITY_2;


    RtlInitializeSid( BedrockBDomainSid,   &BedrockBAuthority, 3 );
    *(RtlSubAuthoritySid( BedrockBDomainSid, 0)) = BEDROCKB_SUBAUTHORITY_0;
    *(RtlSubAuthoritySid( BedrockBDomainSid, 1)) = BEDROCKB_SUBAUTHORITY_1;
    *(RtlSubAuthoritySid( BedrockBDomainSid, 2)) = BEDROCKB_SUBAUTHORITY_2;

    RtlInitializeSid( BedrockCDomainSid,   &BedrockCAuthority, 3 );
    *(RtlSubAuthoritySid( BedrockCDomainSid, 0)) = BEDROCKC_SUBAUTHORITY_0;
    *(RtlSubAuthoritySid( BedrockCDomainSid, 1)) = BEDROCKC_SUBAUTHORITY_1;
    *(RtlSubAuthoritySid( BedrockCDomainSid, 2)) = BEDROCKC_SUBAUTHORITY_2;

    RtlInitializeSid( BedrockDDomainSid,   &BedrockDAuthority, 3 );
    *(RtlSubAuthoritySid( BedrockDDomainSid, 0)) = BEDROCKD_SUBAUTHORITY_0;
    *(RtlSubAuthoritySid( BedrockDDomainSid, 1)) = BEDROCKD_SUBAUTHORITY_1;
    *(RtlSubAuthoritySid( BedrockDDomainSid, 2)) = BEDROCKD_SUBAUTHORITY_2;

    RtlInitializeSid( BedrockEDomainSid,   &BedrockEAuthority, 3 );
    *(RtlSubAuthoritySid( BedrockEDomainSid, 0)) = BEDROCKE_SUBAUTHORITY_0;
    *(RtlSubAuthoritySid( BedrockEDomainSid, 1)) = BEDROCKE_SUBAUTHORITY_1;
    *(RtlSubAuthoritySid( BedrockEDomainSid, 2)) = BEDROCKE_SUBAUTHORITY_2;

    RtlCopySid( SidWithFourSubAuthorities, FredSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( FredSid )) += 1;
    *(RtlSubAuthoritySid( FredSid, 3)) = FRED_RID;

    RtlCopySid( SidWithFourSubAuthorities, WilmaSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( WilmaSid )) += 1;
    *(RtlSubAuthoritySid( WilmaSid, 3)) = WILMA_RID;

    RtlCopySid( SidWithFourSubAuthorities, PebblesSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( PebblesSid )) += 1;
    *(RtlSubAuthoritySid( PebblesSid, 3)) = PEBBLES_RID;

    RtlCopySid( SidWithFourSubAuthorities, DinoSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( DinoSid )) += 1;
    *(RtlSubAuthoritySid( DinoSid, 3)) = DINO_RID;

    RtlCopySid( SidWithFourSubAuthorities, BarneySid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( BarneySid )) += 1;
    *(RtlSubAuthoritySid( BarneySid, 3)) = BARNEY_RID;

    RtlCopySid( SidWithFourSubAuthorities, BettySid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( BettySid )) += 1;
    *(RtlSubAuthoritySid( BettySid, 3)) = BETTY_RID;

    RtlCopySid( SidWithFourSubAuthorities, BambamSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( BambamSid )) += 1;
    *(RtlSubAuthoritySid( BambamSid, 3)) = BAMBAM_RID;

    RtlCopySid( SidWithFourSubAuthorities, FlintstoneSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( FlintstoneSid )) += 1;
    *(RtlSubAuthoritySid( FlintstoneSid, 3)) = FLINTSTONE_RID;

    RtlCopySid( SidWithFourSubAuthorities, RubbleSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( RubbleSid )) += 1;
    *(RtlSubAuthoritySid( RubbleSid, 3)) = RUBBLE_RID;

    RtlCopySid( SidWithFourSubAuthorities, AdultSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( AdultSid )) += 1;
    *(RtlSubAuthoritySid( AdultSid, 3)) = ADULT_RID;

    RtlCopySid( SidWithFourSubAuthorities, ChildSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( ChildSid )) += 1;
    *(RtlSubAuthoritySid( ChildSid, 3)) = CHILD_RID;

    RtlCopySid( SidWithFourSubAuthorities, NeandertholSid, BedrockDomainSid);
    *(RtlSubAuthorityCountSid( NeandertholSid )) += 1;
    *(RtlSubAuthoritySid( NeandertholSid, 3)) = NEANDERTHOL_RID;

    CreateTokenPrivilege =
        RtlConvertLongToLargeInteger(SE_CREATE_TOKEN_PRIVILEGE);
    AssignPrimaryTokenPrivilege =
        RtlConvertLongToLargeInteger(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE);
    LockMemoryPrivilege =
        RtlConvertLongToLargeInteger(SE_LOCK_MEMORY_PRIVILEGE);
    IncreaseQuotaPrivilege =
        RtlConvertLongToLargeInteger(SE_INCREASE_QUOTA_PRIVILEGE);
    UnsolicitedInputPrivilege =
        RtlConvertLongToLargeInteger(SE_UNSOLICITED_INPUT_PRIVILEGE);
    TcbPrivilege =
        RtlConvertLongToLargeInteger(SE_TCB_PRIVILEGE);
    SecurityPrivilege =
        RtlConvertLongToLargeInteger(SE_SECURITY_PRIVILEGE);
    TakeOwnershipPrivilege =
        RtlConvertLongToLargeInteger(SE_TAKE_OWNERSHIP_PRIVILEGE);
    LpcReplyBoostPrivilege =
        RtlConvertLongToLargeInteger(SE_LPC_REPLY_BOOST_PRIVILEGE);
    CreatePagefilePrivilege =
        RtlConvertLongToLargeInteger(SE_CREATE_PAGEFILE_PRIVILEGE);
    IncreaseBasePriorityPrivilege =
        RtlConvertLongToLargeInteger(SE_INC_BASE_PRIORITY_PRIVILEGE);
    SystemProfilePrivilege =
        RtlConvertLongToLargeInteger(SE_SYSTEM_PROFILE_PRIVILEGE);
    SystemtimePrivilege =
        RtlConvertLongToLargeInteger(SE_SYSTEMTIME_PRIVILEGE);
    ProfileSingleProcessPrivilege =
        RtlConvertLongToLargeInteger(SE_PROF_SINGLE_PROCESS_PRIVILEGE);
    CreatePermanentPrivilege =
        RtlConvertLongToLargeInteger(SE_CREATE_PERMANENT_PRIVILEGE);
    BackupPrivilege =
        RtlConvertLongToLargeInteger(SE_BACKUP_PRIVILEGE);
    RestorePrivilege =
        RtlConvertLongToLargeInteger(SE_RESTORE_PRIVILEGE);
    ShutdownPrivilege =
        RtlConvertLongToLargeInteger(SE_SHUTDOWN_PRIVILEGE);
    DebugPrivilege =
        RtlConvertLongToLargeInteger(SE_DEBUG_PRIVILEGE);


    return TRUE;

}
Beispiel #24
0
NTSTATUS
LcFetchRemoteFile (
    _In_  PCFLT_RELATED_OBJECTS FltObjects,
    _In_  PUNICODE_STRING       SourceFile,
    _In_  PUNICODE_STRING       TargetFile,
    _In_  BOOLEAN               UseCustomHandler,
    _Out_ PLARGE_INTEGER        BytesCopied
    )
/*++

Summary:

    This function copies the remote file content to the current file object.

    In order for the remote file to be fetched, make sure that the network redirector
    device is used, i.e. the 'SourceFile' root points to the '\Device\Mup\<path>'.

Arguments:

    FltObjects       - Pointer to the 'FLT_RELATED_OBJECTS' data structure containing
                       opaque handles to this filter, instance, its associated volume and
                       file object.

    SourceFile       - Path to the file to fetch content from.

    TargetFile       - Path to the file to store content to.

    UseCustomHandler - Whether the file should be fetched by the user-mode client.

    BytesCopied      - The amount of bytes copied.

Return Value:

    The return value is the status of the operation.

--*/
{
    NTSTATUS                     status           = STATUS_SUCCESS;
    HANDLE                       sourceFileHandle = NULL;
    IO_STATUS_BLOCK              statusBlock      = { 0 };
    FILE_STANDARD_INFORMATION    standardInfo     = { 0 };
    FILE_END_OF_FILE_INFORMATION eofInfo          = { 0 };

    PAGED_CODE();

    IF_FALSE_RETURN_RESULT(FltObjects  != NULL, STATUS_INVALID_PARAMETER_1);
    IF_FALSE_RETURN_RESULT(SourceFile  != NULL, STATUS_INVALID_PARAMETER_2);
    IF_FALSE_RETURN_RESULT(TargetFile  != NULL, STATUS_INVALID_PARAMETER_3);
    IF_FALSE_RETURN_RESULT(BytesCopied != NULL, STATUS_INVALID_PARAMETER_5);

    FLT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

    *BytesCopied = RtlConvertLongToLargeInteger(0);

    __try
    {
        LOG((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "[LazyCopy] Fetching content from: '%wZ' -> '%wZ'\n", SourceFile, TargetFile));

        if (UseCustomHandler)
        {
            NT_IF_FAIL_LEAVE(LcFetchFileInUserMode(SourceFile, TargetFile, BytesCopied));
        }
        else
        {
            //
            // Open the source file and make sure it's not empty.
            //

            NT_IF_FAIL_LEAVE(LcOpenFile(SourceFile, TargetFile, &sourceFileHandle));

            NT_IF_FAIL_LEAVE(ZwQueryInformationFile(sourceFileHandle, &statusBlock, &standardInfo, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation));
            if (standardInfo.EndOfFile.QuadPart == 0)
            {
                // No need to copy an empty file.
                __leave;
            }

            // Extend the target file, so all readers that wait for the content to be copied will get the actual file size information.
            // Remote file system may return incorrect information, but we are doing it only for the cases, when multiple threads
            // try to access the same file, while we are fetching it.
            eofInfo.EndOfFile.QuadPart = standardInfo.EndOfFile.QuadPart;
            NT_IF_FAIL_LEAVE(FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &eofInfo, sizeof(eofInfo), FileEndOfFileInformation));

            //
            // Copy source file contents into the local (target) file.
            //

            NT_IF_FAIL_LEAVE(LcFetchFileByChunks(
                FltObjects,
                sourceFileHandle,
                &standardInfo.EndOfFile,
                BytesCopied));
        }
    }
    __finally
    {
        if (sourceFileHandle != NULL)
        {
            ZwClose(sourceFileHandle);
        }
    }

    return status;
}
Beispiel #25
0
VOID
DrainTransmit( PDIGI_CONTROLLER_EXTENSION ControllerExt,
               PDIGI_DEVICE_EXTENSION DeviceExt,
               PIRP Irp )
/*++

Routine Description:

   We do the necessary checks to determine if the controller has
   transmitted all the data it has been given.

   The check basically is:

      if( CIN == COUT
          TIN == TOUT
          TBusy == 0 )
          transmit buffer is empty.


   NOTE: Care should be taken when using this function, and at
         what dispatch level it is being called from.  I don't do any
         synch'ing with the WriteQueue in the DeviceObject.  So it is
         potentially possible that data could keep getting put on the
         controller while the function is waiting for it to drain.

Arguments:

   ControllerExt - a pointer to this devices controllers extension.

   DeviceObject - a pointer to this devices object.

   Irp - Pointer to the current Irp request whose context this function
         is being called.  This allows us to determine if the Irp
         has been cancelled.

Return Value:


--*/
{
   PFEP_CHANNEL_STRUCTURE ChInfo;
   PCOMMAND_STRUCT CommandQ;
   COMMAND_STRUCT CmdStruct;
   UCHAR TBusy;
   ULONG count;

   USHORT OrgTout, Tin, Tout;

   TIME DelayInterval;


   ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress +
                                     DeviceExt->ChannelInfo.Offset);

   EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
   Tin = READ_REGISTER_USHORT( &ChInfo->tin );
   Tout = READ_REGISTER_USHORT( &ChInfo->tout );
   TBusy = READ_REGISTER_UCHAR( &ChInfo->tbusy );
   DisableWindow( ControllerExt );

   OrgTout = Tout;

   //
   // Get the command queue info
   //
   CommandQ = ((PCOMMAND_STRUCT)(ControllerExt->VirtualAddress + FEP_CIN));

   EnableWindow( ControllerExt, ControllerExt->Global.Window );
   READ_REGISTER_BUFFER_UCHAR( (PUCHAR)CommandQ,
                               (PUCHAR)&CmdStruct,
                               sizeof(CmdStruct) );
   DisableWindow( ControllerExt );

   //
   // Delay for 10 milliseconds
   //
#if rmm < 807
   DelayInterval = RtlConvertLongToLargeInteger( -10 * 10000 );
#else
   DelayInterval.QuadPart = -10 * 10000;
#endif

   count = 0;

   while( ((Tin != Tout) ||
          (TBusy) ||
          (CmdStruct.cmHead != CmdStruct.cmTail)) &&
          !Irp->Cancel )
   {
      ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL ); // not DPC, or KeDelay won't ever return
      KeDelayExecutionThread( KernelMode,
                              FALSE,
                              &DelayInterval );

      EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
      Tin = READ_REGISTER_USHORT( &ChInfo->tin );
      Tout = READ_REGISTER_USHORT( &ChInfo->tout );
      TBusy = READ_REGISTER_UCHAR( &ChInfo->tbusy );
      DisableWindow( ControllerExt );

      EnableWindow( ControllerExt, ControllerExt->Global.Window );
      READ_REGISTER_BUFFER_UCHAR( (PUCHAR)CommandQ,
                                  (PUCHAR)&CmdStruct,
                                  sizeof(CmdStruct) );
      DisableWindow( ControllerExt );

      if( Tout != OrgTout )
      {
         count = 0;
         OrgTout = Tout;
      }

      if( count++ > 2500 )
      {
         //
         // We have waited for 25 seconds and haven't seen the transmit
         // buffer change.  Assume we are in a deadlock flow control state
         // and exit!
         //

         //
         // We go ahead and flush the transmit queue because a close
         // may be following soon, and we don't want it to have to
         // wait again.  Basically, it had its chance to drain.
         //
         FlushTransmitBuffer( ControllerExt, DeviceExt );

         break;
      }

   }

}  // end DrainTransmit
DualErr 
CPGPdiskInterface::UnmountPGPdisk(PGPUInt8 drive, PGPBoolean isThisEmergency)
{
	DualErr		derr;
	PGPBoolean	removedPGPdisk, unmountedChildren;
	PGPdisk		*pPGD;
	PGPUInt32	i	= 0;

	removedPGPdisk = unmountedChildren = FALSE;

	pgpAssert(IsLegalDriveNumber(drive));

	// Verify that the PGPdisk exists and is mounted.
	if (NULL==(int)(pPGD = mPGPdisks.FindPGPdisk(drive)))
		derr = DualErr(kPGDMinorError_PGPdiskNotMounted);

	// If this PGPdisk has other PGPdisks mounted on it, we must perform a
	// depth-first unmount of all those PGPdisks first.

	while (derr.IsntError())
	{
		PGPdisk *pClient;

		if (!(pClient = Interface->mPGPdisks.EnumPGPdisks(i++)))
			break;

		if (!IsUNCPath(pClient->GetPath()) &&
			(pClient->GetLocalHostDrive() == drive))
		{
			i = 0;
			derr = UnmountPGPdisk(pClient->GetDrive(), isThisEmergency);

			if (isThisEmergency)
				derr = DualErr::NoError;

			unmountedChildren = derr.IsntError();
		}
	}

	// Check if the PGPdisk has open files.
	if (derr.IsntError())
	{
		// If we unmounted any children, we may have to wait a little while
		// for the system to flush its cache. Try about 10 times.

		if (unmountedChildren)
		{
			i = 0;

			while (pPGD->HasOpenFiles() && (i++ < kMaxCheckOpenFilesAttempts))
			{
				LARGE_INTEGER	ticks	= 
					RtlConvertLongToLargeInteger(-500 * 10000);

				KeDelayExecutionThread(KernelMode, FALSE, &ticks);
			}
		}

		if (pPGD->HasOpenFiles())
			derr = DualErr(kPGDMinorError_FilesOpenOnDrive);

		if (isThisEmergency)
			derr = DualErr::NoError;
	}

	// Remove the object from the global list and attempt the unmount.
	if (derr.IsntError())
	{
		mPGPdisks.RemovePGPdisk(pPGD);
		removedPGPdisk = TRUE;

		derr = pPGD->Unmount(isThisEmergency);
	}

	// Delete the PGPdisk object.
	if (derr.IsntError())
	{
		delete pPGD;
	}

	// Cleanup if an error occurred;
	if (derr.IsError())
	{
		if (removedPGPdisk && pPGD->Mounted())
			mPGPdisks.AddPGPdisk(pPGD);
	}

	return derr;
}
Beispiel #27
0
int
WSPAPI
WSPShutdown(
    IN SOCKET Handle,
    IN int HowTo,
    OUT LPINT lpErrno
    )

/*++

Routine Description:

    This routine is used on all types of sockets to disable reception,
    transmission, or both.

    If how is SD_RECEIVE, subsequent receives on the socket will be
    disallowed. This has no effect on the lower protocol layers. For TCP
    sockets, if there is still data queued on the socket waiting to be
    received, or data arrives subsequently, the connection is reset, since the
    data cannot be delivered to the user. For UDP sockets, incoming datagrams
    are accepted and queued. In no case will an ICMP error packet
    be generated.

    If how is SD_SEND, subsequent sends on the socket are disallowed. For TCP
    sockets, a FIN will be sent. Setting how to SD_BOTH disables both sends
    and receives as described above.

    Note that WSPShutdown() does not close the socket, and resources attached
    to the socket will not be freed until WSPCloseSocket() is invoked.

    WSPShutdown() does not block regardless of the SO_LINGER setting on the
    socket. A WinSock SPI client should not rely on being able to re-use a
    socket after it has been shut down. In particular, a WinSock service
    provider is not required to support the use of WSPConnect() on such a
    socket.

Arguments:

    s - A descriptor identifying a socket.

    how - A flag that describes what types of operation will no longer be
        allowed.

    lpErrno - A pointer to the error code.

Return Value:

    If no error occurs, WSPShutdown() returns 0. Otherwise, a value of
        SOCKET_ERROR is returned, and a specific error code is available
        in lpErrno.

--*/

{

    NTSTATUS status;
	PWINSOCK_TLS_DATA	tlsData;
    PSOCKET_INFORMATION socket;
    IO_STATUS_BLOCK ioStatusBlock;
    int err;
    AFD_PARTIAL_DISCONNECT_INFO disconnectInfo;
    DWORD notificationEvent;

    WS_ENTER( "WSPShutdown", (PVOID)Handle, (PVOID)HowTo, NULL, NULL );

    WS_ASSERT( lpErrno != NULL );

    err = SockEnterApi( &tlsData );

    if( err != NO_ERROR ) {

        WS_EXIT( "WSPShutdown", SOCKET_ERROR, TRUE );
        *lpErrno = err;
        return SOCKET_ERROR;

    }

    //
    // Set up locals so that we know how to clean up on exit.
    //

    socket = NULL;

    //
    // Find a pointer to the socket structure corresponding to the
    // passed-in handle.
    //

    socket = SockFindAndReferenceSocket( Handle, TRUE );

    if ( socket == NULL ) {

        err = WSAENOTSOCK;
        goto exit;

    }

    //
    // Acquire the lock that protect this socket.
    //

    SockAcquireSocketLockExclusive( socket );

    //
    // If this is not a datagram socket, then it must be connected in order
    // for WSPShutdown() to be a legal operation.
    //

    if ( !IS_DGRAM_SOCK(socket) &&
             !SockIsSocketConnected( socket ) ) {

        err = WSAENOTCONN;
        goto exit;

    }

    //
    // Translate the How parameter into the AFD disconnect information
    // structure.
    //

    switch ( HowTo ) {

    case SD_RECEIVE:

        disconnectInfo.DisconnectMode = AFD_PARTIAL_DISCONNECT_RECEIVE;
        socket->ReceiveShutdown = TRUE;
        notificationEvent = WSH_NOTIFY_SHUTDOWN_RECEIVE;
        break;

    case SD_SEND:

        disconnectInfo.DisconnectMode = AFD_PARTIAL_DISCONNECT_SEND;
        socket->SendShutdown = TRUE;
        notificationEvent = WSH_NOTIFY_SHUTDOWN_SEND;
        break;

    case SD_BOTH:

        disconnectInfo.DisconnectMode =
            AFD_PARTIAL_DISCONNECT_RECEIVE | AFD_PARTIAL_DISCONNECT_SEND;
        socket->ReceiveShutdown = TRUE;
        socket->SendShutdown = TRUE;
        notificationEvent = WSH_NOTIFY_SHUTDOWN_ALL;
        break;

    default:

        err = WSAEINVAL;
        goto exit;

    }


#ifdef _AFD_SAN_SWITCH_
	//
	// If we have a SAN socket open, close that first
	//
	if (SockSanEnabled && socket->SanSocket &&
		socket->SanSocket->IsConnected == CONNECTED) {

		err = SockSanShutdown(socket, HowTo);
		
		goto exit;
	}
#endif //_AFD_SAN_SWITCH_


    // !!! temporary HACK for tp4!

    if ( (HowTo == 1 || HowTo == 2) && socket->AddressFamily == AF_OSI ) {

        disconnectInfo.DisconnectMode = AFD_ABORTIVE_DISCONNECT;

    }

    //
    // This routine should complete immediately, not when the remote client
    // acknowledges the disconnect.
    //

    disconnectInfo.Timeout = RtlConvertLongToLargeInteger( -1 );

    IF_DEBUG(CLOSE) {

        WS_PRINT(( "starting WSPShutdown for socket %lx\n", Handle ));

    }

    //
    // Send the IOCTL to AFD for processing.
    //

    status = NtDeviceIoControlFile(
                 socket->HContext.Handle,
                 tlsData->EventHandle,
                 NULL,                      // APC Routine
                 NULL,                      // APC Context
                 &ioStatusBlock,
                 IOCTL_AFD_PARTIAL_DISCONNECT,
                 &disconnectInfo,
                 sizeof(disconnectInfo),
                 NULL,                      // OutputBuffer
                 0L                         // OutputBufferLength
                 );

    if ( status == STATUS_PENDING ) {

        SockReleaseSocketLock( socket );
        SockWaitForSingleObject(
            tlsData->EventHandle,
            Handle,
            SOCK_NEVER_CALL_BLOCKING_HOOK,
            SOCK_NO_TIMEOUT
            );
        SockAcquireSocketLockExclusive( socket );
        status = ioStatusBlock.Status;

    }

    if ( !NT_SUCCESS(status) ) {

        err = SockNtStatusToSocketError( status );
        goto exit;

    }

    //
    // Notify the helper DLL that the socket has been shut down.
    //

    err = SockNotifyHelperDll( socket, notificationEvent );

    if ( err != NO_ERROR ) {

        goto exit;

    }

exit:

    IF_DEBUG(SHUTDOWN) {

        if ( err != NO_ERROR ) {

            WS_PRINT(( "WSPShutdown(%ld) on socket %lx (%lx) failed: %ld.\n",
                           HowTo, Handle, socket, err ));

        } else {

            WS_PRINT(( "WSPShutdown(%ld) on socket %lx (%lx) succeeded.\n",
                           HowTo, Handle, socket ));

        }

    }

    if ( socket != NULL ) {

        SockReleaseSocketLock( socket );
        SockDereferenceSocket( socket );

    }

    if ( err != NO_ERROR ) {

        WS_EXIT( "WSPShutdown", SOCKET_ERROR, TRUE );
        *lpErrno = err;
        return SOCKET_ERROR;

    }

    WS_EXIT( "WSPShutdown", NO_ERROR, FALSE );
    return NO_ERROR;

}   // WSPShutdown