Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refcount redirection close #106

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions UsbDk/ControlDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1025,9 +1025,9 @@ NTSTATUS CUsbDkControlDevice::AddRedirectionToSet(const USB_DK_DEVICE_ID &Device
return STATUS_SUCCESS;
}

NTSTATUS CUsbDkControlDevice::RemoveRedirect(const USB_DK_DEVICE_ID &DeviceId)
NTSTATUS CUsbDkControlDevice::RemoveRedirect(const USB_DK_DEVICE_ID &DeviceId, ULONG pid)
{
if (NotifyRedirectorRemovalStarted(DeviceId))
if (NotifyRedirectorRemovalStarted(DeviceId, pid))
{
auto res = ResetUsbDevice(DeviceId, false);
if (NT_SUCCESS(res))
Expand Down Expand Up @@ -1079,9 +1079,8 @@ bool CUsbDkControlDevice::NotifyRedirectorAttached(CRegText *DeviceID, CRegText
return m_Redirections.ModifyOne(&ID, [RedirectorDevice](CUsbDkRedirection *R){ R->NotifyRedirectorCreated(RedirectorDevice); });
}

bool CUsbDkControlDevice::NotifyRedirectorRemovalStarted(const USB_DK_DEVICE_ID &ID)
bool CUsbDkControlDevice::NotifyRedirectorRemovalStarted(const USB_DK_DEVICE_ID &ID, ULONG pid)
{
ULONG pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
return m_Redirections.ModifyOne(&ID, [](CUsbDkRedirection *R){ R->NotifyRedirectionRemovalStarted(); }, pid);
}

Expand Down
4 changes: 2 additions & 2 deletions UsbDk/ControlDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ class CUsbDkControlDevice : private CWdfControlDevice, public CAllocatable<USBDK

void ClearHideRules();

NTSTATUS RemoveRedirect(const USB_DK_DEVICE_ID &DeviceId);
NTSTATUS RemoveRedirect(const USB_DK_DEVICE_ID &DeviceId, ULONG pid);
NTSTATUS GetConfigurationDescriptor(const USB_DK_CONFIG_DESCRIPTOR_REQUEST &Request,
PUSB_CONFIGURATION_DESCRIPTOR Descriptor,
size_t *OutputBuffLen);
Expand Down Expand Up @@ -309,7 +309,7 @@ class CUsbDkControlDevice : private CWdfControlDevice, public CAllocatable<USBDK
}

bool NotifyRedirectorAttached(CRegText *DeviceID, CRegText *InstanceID, CUsbDkFilterDevice *RedirectorDevice);
bool NotifyRedirectorRemovalStarted(const USB_DK_DEVICE_ID &ID);
bool NotifyRedirectorRemovalStarted(const USB_DK_DEVICE_ID &ID, ULONG pid);
bool WaitForDetachment(const USB_DK_DEVICE_ID &ID);

private:
Expand Down
25 changes: 23 additions & 2 deletions UsbDk/FilterDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,33 @@ NTSTATUS CUsbDkFilterDeviceInit::Configure(ULONG InstanceNumber)
SetFileEventCallbacks([](_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDFFILEOBJECT FileObject)
{
UNREFERENCED_PARAMETER(FileObject);
UsbDkFilterGetContext(Device)->UsbDkFilter->OnFileCreate(Request);
auto filter = UsbDkFilterGetContext(Device)->UsbDkFilter;
filter->m_open_count.AddRef();
filter->OnFileCreate(Request);
},
[](_In_ WDFFILEOBJECT FileObject)
{
WDFDEVICE Device = WdfFileObjectGetDevice(FileObject);
Strategy(Device)->OnClose();
auto filter = UsbDkFilterGetContext(Device)->UsbDkFilter;
ULONG pid = 0; // zero means always match

// Check PID only if there are multiple open references to the file.
// If this was the last reference, always close the redirection.
//
// This callback function might run in a different process-context
// than the initiator process, therefore the 'current process ID'
// isn't always the ID of the 'owning' process.
//
// In the worst case, the USB redirection will be kept until the last
// open file handle to the device is closed.
//
// From KMDF 1.21, there's a new method that should give us the expected ID:
// WdfFileObjectGetInitiatorProcessId(FileObject)

if (filter->m_open_count.Release()) {
pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
}
Strategy(Device)->OnClose(pid);
},
WDF_NO_EVENT_CALLBACK);

Expand Down
3 changes: 3 additions & 0 deletions UsbDk/FilterDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ class CUsbDkFilterDevice : public CWdfDevice,
{ m_SerialNumber = Number; }

void OnFileCreate(WDFREQUEST Request);

CWdmRefCounter m_open_count;

private:
~CUsbDkFilterDevice()
{
Expand Down
3 changes: 2 additions & 1 deletion UsbDk/FilterStrategy.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class CUsbDkFilterStrategy
CUsbDkControlDevice* GetControlDevice()
{ return m_ControlDevice; }

virtual void OnClose(){}
virtual void OnClose(ULONG pid)
{ UNREFERENCED_PARAMETER(pid); }

protected:
CUsbDkFilterDevice *m_Owner = nullptr;
Expand Down
6 changes: 3 additions & 3 deletions UsbDk/RedirectorStrategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ NTSTATUS CUsbDkRedirectorStrategy::Create(CUsbDkFilterDevice *Owner)
return status;
}

using USBDK_REDIRECTOR_REQUEST_CONTEXT = struct : public USBDK_TARGET_REQUEST_CONTEXT
struct USBDK_REDIRECTOR_REQUEST_CONTEXT : public USBDK_TARGET_REQUEST_CONTEXT
{
bool PreprocessingDone;

Expand Down Expand Up @@ -626,13 +626,13 @@ size_t CUsbDkRedirectorStrategy::GetRequestContextSize()
return sizeof(USBDK_REDIRECTOR_REQUEST_CONTEXT);
}

void CUsbDkRedirectorStrategy::OnClose()
void CUsbDkRedirectorStrategy::OnClose(ULONG pid)
{
USB_DK_DEVICE_ID ID;
UsbDkFillIDStruct(&ID, *m_DeviceID->begin(), *m_InstanceID->begin());
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_REDIRECTOR, "%!FUNC!");

auto status = m_ControlDevice->RemoveRedirect(ID);
auto status = m_ControlDevice->RemoveRedirect(ID, pid);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_REDIRECTOR, "%!FUNC! RemoveRedirect failed: %!STATUS!", status);
Expand Down
2 changes: 1 addition & 1 deletion UsbDk/RedirectorStrategy.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class CUsbDkRedirectorStrategy : public CUsbDkHiderStrategy
size_t InputBufferLength,
ULONG IoControlCode) override;

virtual void OnClose() override;
virtual void OnClose(ULONG pid) override;

void SetDeviceID(CRegText *DevID)
{ m_DeviceID = DevID; }
Expand Down
2 changes: 1 addition & 1 deletion UsbDk/UsbTarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "Urb.h"
#include "WdfRequest.h"

using USBDK_TARGET_REQUEST_CONTEXT = struct : public WDF_REQUEST_CONTEXT
struct USBDK_TARGET_REQUEST_CONTEXT : public WDF_REQUEST_CONTEXT
{
ULONG64 RequestId;
};
Expand Down