NTSTATUS STATUS_PENDING when sending IOCTL from kernel thread

Viewed 64

I have following method defined in one of my headers :

typedef struct _BEEP_SET_PARAMETERS {
    ULONG Frequency;
    ULONG Duration;
} BEEP_SET_PARAMETERS, * PBEEP_SET_PARAMETERS;

inline void DoBeepIoctl()
{
    UNICODE_STRING deviceName = RTL_CONSTANT_STRING(L"\\Device\\Beep");

    OBJECT_ATTRIBUTES objectAttributes;
    InitializeObjectAttributes(&objectAttributes, &deviceName, NULL, NULL, NULL);

    HANDLE beepDriver;
    IO_STATUS_BLOCK IoStatus;
    NTSTATUS status = ZwOpenFile(&beepDriver, 0, &objectAttributes, &IoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN);

    if (!beepDriver)
    {
        Print("Initialization failed !");
        return;
    }

    if (status == STATUS_SUCCESS)
    {
        ULONG IOCTL_BEEP = CTL_CODE(FILE_DEVICE_BEEP, 0, METHOD_BUFFERED, FILE_ANY_ACCESS);
        ULONG returned = 0;

        BEEP_SET_PARAMETERS BeepSettings;
        BeepSettings.Duration = 1000;
        BeepSettings.Frequency = 500;

        status = ZwDeviceIoControlFile(beepDriver, NULL, NULL, NULL, &IoStatus, IOCTL_BEEP, &BeepSettings, sizeof(BeepSettings), &returned, 0);
        Print("ZwDeviceIoControlFile status is %X", status);
    }
    else
    {
        Print("status is not success %X", status);
    }
}

When I call directly from driver entry like this :

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    UNREFERENCED_PARAMETER(DriverObject);
    UNREFERENCED_PARAMETER(RegistryPath);
    Print("Beep");
    DoBeepIoctl();
}

It exectues properly.

However when I call it from thread spawned via PsCreateSystemThread it return status NTSTATUS 0x00000103 which is equal to STATUS_PENDING and no beep is ever heard.

Thread creation snippet looks like this :

HANDLE threadHandle = NULL;
NTSTATUS status = PsCreateSystemThread(&threadHandle, GENERIC_ALL, NULL, NULL, NULL, (PKSTART_ROUTINE)start, NULL);

And last but not least the thread routine itself :

void MainThread()
{
    Print("Do the beep");
    DoBeepIoctl();
}

Question is what am I missing to call Beep.sys IOCTL successfully from spawned thread ?

0 Answers
Related