wineusb.c 21.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * USB root device enumerator using libusb
 *
 * Copyright 2020 Zebediah Figura
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <assert.h>
#include <stdarg.h>
23
#include <stdbool.h>
24
#include <stdint.h>
25 26 27 28 29 30 31 32 33 34 35 36 37 38
#include <stdlib.h>

#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winioctl.h"
#include "winternl.h"
#include "ddk/wdm.h"
#include "ddk/usb.h"
#include "ddk/usbioctl.h"
#include "wine/asm.h"
#include "wine/debug.h"
#include "wine/list.h"

39 40
#include "unixlib.h"

41 42
WINE_DEFAULT_DEBUG_CHANNEL(wineusb);

43
#ifdef __ASM_USE_FASTCALL_WRAPPER
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59

extern void * WINAPI wrap_fastcall_func1( void *func, const void *a );
__ASM_STDCALL_FUNC( wrap_fastcall_func1, 8,
                   "popl %ecx\n\t"
                   "popl %eax\n\t"
                   "xchgl (%esp),%ecx\n\t"
                   "jmp *%eax" );

#define call_fastcall_func1(func,a) wrap_fastcall_func1(func,a)

#else

#define call_fastcall_func1(func,a) func(a)

#endif

60 61 62 63 64 65 66 67 68 69 70 71 72 73
#define DECLARE_CRITICAL_SECTION(cs) \
    static CRITICAL_SECTION cs; \
    static CRITICAL_SECTION_DEBUG cs##_debug = \
    { 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
      0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
    static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 };

DECLARE_CRITICAL_SECTION(wineusb_cs);

static struct list device_list = LIST_INIT(device_list);

struct usb_device
{
    struct list entry;
74
    BOOL removed;
75 76 77

    DEVICE_OBJECT *device_obj;

78
    bool interface;
79
    int16_t interface_index;
80

81
    uint8_t class, subclass, protocol, busnum, portnum;
82

83
    uint16_t vendor, product, revision, usbver;
84

85
    struct unix_device *unix_device;
86 87

    LIST_ENTRY irp_list;
88 89 90
};

static DRIVER_OBJECT *driver_obj;
91 92
static DEVICE_OBJECT *bus_fdo, *bus_pdo;

93
static void destroy_unix_device(struct unix_device *unix_device)
94
{
95
    struct usb_destroy_device_params params =
96
    {
97 98
        .device = unix_device,
    };
99

100
    WINE_UNIX_CALL(unix_usb_destroy_device, &params);
101 102
}

103
static void add_unix_device(const struct usb_add_device_event *event)
104 105 106 107 108 109
{
    static unsigned int name_index;
    struct usb_device *device;
    DEVICE_OBJECT *device_obj;
    UNICODE_STRING string;
    NTSTATUS status;
110
    WCHAR name[26];
111

112 113
    TRACE("Adding new device %p, vendor %04x, product %04x.\n", event->device,
            event->vendor, event->product);
114

115
    swprintf(name, ARRAY_SIZE(name), L"\\Device\\USBPDO-%u", name_index++);
116 117 118 119
    RtlInitUnicodeString(&string, name);
    if ((status = IoCreateDevice(driver_obj, sizeof(*device), &string,
            FILE_DEVICE_USB, 0, FALSE, &device_obj)))
    {
120
        ERR("Failed to create device, status %#lx.\n", status);
121 122 123 124 125
        return;
    }

    device = device_obj->DeviceExtension;
    device->device_obj = device_obj;
126
    device->unix_device = event->device;
127
    InitializeListHead(&device->irp_list);
128
    device->removed = FALSE;
129

130 131 132
    device->interface = event->interface;
    device->interface_index = event->interface_index;

133 134 135
    device->class = event->class;
    device->subclass = event->subclass;
    device->protocol = event->protocol;
136 137 138
    device->busnum = event->busnum;
    device->portnum = event->portnum;

139 140 141
    device->vendor = event->vendor;
    device->product = event->product;
    device->revision = event->revision;
142
    device->usbver = event->usbver;
143

144 145 146 147
    EnterCriticalSection(&wineusb_cs);
    list_add_tail(&device_list, &device->entry);
    LeaveCriticalSection(&wineusb_cs);

148 149 150
    IoInvalidateDeviceRelations(bus_pdo, BusRelations);
}

151
static void remove_unix_device(struct unix_device *unix_device)
152 153 154
{
    struct usb_device *device;

155
    TRACE("Removing device %p.\n", unix_device);
156 157 158 159

    EnterCriticalSection(&wineusb_cs);
    LIST_FOR_EACH_ENTRY(device, &device_list, struct usb_device, entry)
    {
160
        if (device->unix_device == unix_device)
161
        {
162 163 164 165 166
            if (!device->removed)
            {
                device->removed = TRUE;
                list_remove(&device->entry);
            }
167 168 169 170
            break;
        }
    }
    LeaveCriticalSection(&wineusb_cs);
171 172

    IoInvalidateDeviceRelations(bus_pdo, BusRelations);
173 174
}

175
static HANDLE event_thread;
176

177 178 179 180 181 182 183 184 185 186
static void complete_irp(IRP *irp)
{
    EnterCriticalSection(&wineusb_cs);
    RemoveEntryList(&irp->Tail.Overlay.ListEntry);
    LeaveCriticalSection(&wineusb_cs);

    irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(irp, IO_NO_INCREMENT);
}

187 188 189
static DWORD CALLBACK event_thread_proc(void *arg)
{
    struct usb_event event;
190
    struct usb_main_loop_params params =
191
    {
192 193
        .event = &event,
    };
194

195
    TRACE("Starting event thread.\n");
196

197 198 199 200 201
    if (WINE_UNIX_CALL(unix_usb_init, NULL) != STATUS_SUCCESS)
        return 0;

    while (WINE_UNIX_CALL(unix_usb_main_loop, &params) == STATUS_PENDING)
    {
202 203
        switch (event.type)
        {
204
            case USB_EVENT_ADD_DEVICE:
205
                add_unix_device(&event.u.added_device);
206 207
                break;

208 209 210 211
            case USB_EVENT_REMOVE_DEVICE:
                remove_unix_device(event.u.removed_device);
                break;

212 213 214
            case USB_EVENT_TRANSFER_COMPLETE:
                complete_irp(event.u.completed_irp);
                break;
215 216
        }
    }
217 218 219

    TRACE("Shutting down event thread.\n");
    return 0;
220 221
}

222 223 224 225 226 227 228 229 230
static NTSTATUS fdo_pnp(IRP *irp)
{
    IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
    NTSTATUS ret;

    TRACE("irp %p, minor function %#x.\n", irp, stack->MinorFunction);

    switch (stack->MinorFunction)
    {
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
        case IRP_MN_QUERY_DEVICE_RELATIONS:
        {
            struct usb_device *device;
            DEVICE_RELATIONS *devices;
            unsigned int i = 0;

            if (stack->Parameters.QueryDeviceRelations.Type != BusRelations)
            {
                FIXME("Unhandled device relations type %#x.\n", stack->Parameters.QueryDeviceRelations.Type);
                break;
            }

            EnterCriticalSection(&wineusb_cs);

            if (!(devices = ExAllocatePool(PagedPool,
                    offsetof(DEVICE_RELATIONS, Objects[list_count(&device_list)]))))
            {
                LeaveCriticalSection(&wineusb_cs);
                irp->IoStatus.Status = STATUS_NO_MEMORY;
                break;
            }

            LIST_FOR_EACH_ENTRY(device, &device_list, struct usb_device, entry)
            {
                devices->Objects[i++] = device->device_obj;
                call_fastcall_func1(ObfReferenceObject, device->device_obj);
            }

            LeaveCriticalSection(&wineusb_cs);

            devices->Count = i;
            irp->IoStatus.Information = (ULONG_PTR)devices;
            irp->IoStatus.Status = STATUS_SUCCESS;
            break;
        }

267
        case IRP_MN_START_DEVICE:
268 269
            event_thread = CreateThread(NULL, 0, event_thread_proc, NULL, 0, NULL);

270 271 272
            irp->IoStatus.Status = STATUS_SUCCESS;
            break;

273 274 275 276 277
        case IRP_MN_SURPRISE_REMOVAL:
            irp->IoStatus.Status = STATUS_SUCCESS;
            break;

        case IRP_MN_REMOVE_DEVICE:
278 279 280
        {
            struct usb_device *device, *cursor;

281
            WINE_UNIX_CALL(unix_usb_exit, NULL);
282 283 284
            WaitForSingleObject(event_thread, INFINITE);
            CloseHandle(event_thread);

285
            EnterCriticalSection(&wineusb_cs);
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
            /* Normally we unlink all devices either:
             *
             * - as a result of hot-unplug, which unlinks the device, and causes
             *   a subsequent IRP_MN_REMOVE_DEVICE which will free it;
             *
             * - if the parent is deleted (at shutdown time), in which case
             *   ntoskrnl will send us IRP_MN_SURPRISE_REMOVAL and
             *   IRP_MN_REMOVE_DEVICE unprompted.
             *
             * But we can get devices hotplugged between when shutdown starts
             * and now, in which case they'll be stuck in this list and never
             * freed.
             *
             * FIXME: This is still broken, though. If a device is hotplugged
             * and then removed, it'll be unlinked and never freed. */
301 302
            LIST_FOR_EACH_ENTRY_SAFE(device, cursor, &device_list, struct usb_device, entry)
            {
303
                assert(!device->removed);
304
                destroy_unix_device(device->unix_device);
305 306 307 308 309
                list_remove(&device->entry);
                IoDeleteDevice(device->device_obj);
            }
            LeaveCriticalSection(&wineusb_cs);

310 311 312 313 314 315
            irp->IoStatus.Status = STATUS_SUCCESS;
            IoSkipCurrentIrpStackLocation(irp);
            ret = IoCallDriver(bus_pdo, irp);
            IoDetachDevice(bus_pdo);
            IoDeleteDevice(bus_fdo);
            return ret;
316
        }
317 318 319 320 321 322 323 324 325

        default:
            FIXME("Unhandled minor function %#x.\n", stack->MinorFunction);
    }

    IoSkipCurrentIrpStackLocation(irp);
    return IoCallDriver(bus_pdo, irp);
}

326 327 328 329 330 331 332 333
struct string_buffer
{
    WCHAR *string;
    size_t len;
};

static void WINAPIV append_id(struct string_buffer *buffer, const WCHAR *format, ...)
{
334
    va_list args;
335 336 337
    WCHAR *string;
    int len;

338
    va_start(args, format);
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356

    len = _vsnwprintf(NULL, 0, format, args) + 1;
    if (!(string = ExAllocatePool(PagedPool, (buffer->len + len) * sizeof(WCHAR))))
    {
        if (buffer->string)
            ExFreePool(buffer->string);
        buffer->string = NULL;
        return;
    }
    if (buffer->string)
    {
        memcpy(string, buffer->string, buffer->len * sizeof(WCHAR));
        ExFreePool(buffer->string);
    }
    _vsnwprintf(string + buffer->len, len, format, args);
    buffer->string = string;
    buffer->len += len;

357
    va_end(args);
358 359 360
}

static void get_device_id(const struct usb_device *device, struct string_buffer *buffer)
361
{
362
    if (device->interface)
363 364
        append_id(buffer, L"USB\\VID_%04X&PID_%04X&MI_%02X",
                device->vendor, device->product, device->interface_index);
365
    else
366
        append_id(buffer, L"USB\\VID_%04X&PID_%04X", device->vendor, device->product);
367 368
}

369 370 371 372 373
static void get_instance_id(const struct usb_device *device, struct string_buffer *buffer)
{
    append_id(buffer, L"%u&%u&%u&%u", device->usbver, device->revision, device->busnum, device->portnum);
}

374
static void get_hardware_ids(const struct usb_device *device, struct string_buffer *buffer)
375
{
376
    if (device->interface)
377 378
        append_id(buffer, L"USB\\VID_%04X&PID_%04X&REV_%04X&MI_%02X",
                device->vendor, device->product, device->revision, device->interface_index);
379
    else
380 381 382
        append_id(buffer, L"USB\\VID_%04X&PID_%04X&REV_%04X",
                device->vendor, device->product, device->revision);

383
    get_device_id(device, buffer);
384
    append_id(buffer, L"");
385 386
}

387
static void get_compatible_ids(const struct usb_device *device, struct string_buffer *buffer)
388
{
389 390 391 392 393 394 395 396 397 398 399 400 401 402
    if (device->interface_index != -1)
    {
        append_id(buffer, L"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
                device->class, device->subclass, device->protocol);
        append_id(buffer, L"USB\\Class_%02x&SubClass_%02x", device->class, device->subclass);
        append_id(buffer, L"USB\\Class_%02x", device->class);
    }
    else
    {
        append_id(buffer, L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
                device->class, device->subclass, device->protocol);
        append_id(buffer, L"USB\\DevClass_%02x&SubClass_%02x", device->class, device->subclass);
        append_id(buffer, L"USB\\DevClass_%02x", device->class);
    }
403
    append_id(buffer, L"");
404 405
}

406
static NTSTATUS query_id(struct usb_device *device, IRP *irp, BUS_QUERY_ID_TYPE type)
407
{
408
    struct string_buffer buffer = {0};
409

410 411
    TRACE("type %#x.\n", type);

412 413 414
    switch (type)
    {
        case BusQueryDeviceID:
415
            get_device_id(device, &buffer);
416 417 418
            break;

        case BusQueryInstanceID:
419
            get_instance_id(device, &buffer);
420 421
            break;

422
        case BusQueryHardwareIDs:
423
            get_hardware_ids(device, &buffer);
424 425
            break;

426
        case BusQueryCompatibleIDs:
427
            get_compatible_ids(device, &buffer);
428 429
            break;

430 431 432 433 434
        default:
            FIXME("Unhandled ID query type %#x.\n", type);
            return irp->IoStatus.Status;
    }

435 436 437 438
    if (!buffer.string)
        return STATUS_NO_MEMORY;

    irp->IoStatus.Information = (ULONG_PTR)buffer.string;
439 440 441
    return STATUS_SUCCESS;
}

442 443 444 445 446 447 448 449 450 451 452 453 454 455
static void remove_pending_irps(struct usb_device *device)
{
    LIST_ENTRY *entry;
    IRP *irp;

    while ((entry = RemoveHeadList(&device->irp_list)) != &device->irp_list)
    {
        irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
        irp->IoStatus.Status = STATUS_DELETE_PENDING;
        irp->IoStatus.Information = 0;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
    }
}

456 457 458
static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
{
    IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
459
    struct usb_device *device = device_obj->DeviceExtension;
460 461 462 463 464 465
    NTSTATUS ret = irp->IoStatus.Status;

    TRACE("device_obj %p, irp %p, minor function %#x.\n", device_obj, irp, stack->MinorFunction);

    switch (stack->MinorFunction)
    {
466 467 468 469
        case IRP_MN_QUERY_ID:
            ret = query_id(device, irp, stack->Parameters.QueryId.IdType);
            break;

470
        case IRP_MN_QUERY_CAPABILITIES:
471 472 473 474 475 476 477 478 479 480
        {
            DEVICE_CAPABILITIES *caps = stack->Parameters.DeviceCapabilities.Capabilities;

            caps->RawDeviceOK = 1;

            ret = STATUS_SUCCESS;
            break;
        }

        case IRP_MN_START_DEVICE:
481 482 483
            ret = STATUS_SUCCESS;
            break;

484
        case IRP_MN_SURPRISE_REMOVAL:
485
            EnterCriticalSection(&wineusb_cs);
486
            remove_pending_irps(device);
487 488 489 490 491
            if (!device->removed)
            {
                device->removed = TRUE;
                list_remove(&device->entry);
            }
492
            LeaveCriticalSection(&wineusb_cs);
493 494
            ret = STATUS_SUCCESS;
            break;
495

496
        case IRP_MN_REMOVE_DEVICE:
497
            assert(device->removed);
498
            remove_pending_irps(device);
499

500
            destroy_unix_device(device->unix_device);
501

502
            IoDeleteDevice(device->device_obj);
503 504 505 506 507 508 509 510 511 512 513 514
            ret = STATUS_SUCCESS;
            break;

        default:
            FIXME("Unhandled minor function %#x.\n", stack->MinorFunction);
    }

    irp->IoStatus.Status = ret;
    IoCompleteRequest(irp, IO_NO_INCREMENT);
    return ret;
}

515 516
static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp)
{
517 518 519
    if (device == bus_fdo)
        return fdo_pnp(irp);
    return pdo_pnp(device, irp);
520 521
}

522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
static NTSTATUS usb_submit_urb(struct usb_device *device, IRP *irp)
{
    URB *urb = IoGetCurrentIrpStackLocation(irp)->Parameters.Others.Argument1;
    NTSTATUS status;

    TRACE("type %#x.\n", urb->UrbHeader.Function);

    switch (urb->UrbHeader.Function)
    {
        case URB_FUNCTION_ABORT_PIPE:
        {
            LIST_ENTRY *entry, *mark;

            /* The documentation states that URB_FUNCTION_ABORT_PIPE may
             * complete before outstanding requests complete, so we don't need
             * to wait for them. */
            EnterCriticalSection(&wineusb_cs);
            mark = &device->irp_list;
            for (entry = mark->Flink; entry != mark; entry = entry->Flink)
            {
                IRP *queued_irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
                struct usb_cancel_transfer_params params =
                {
                    .transfer = queued_irp->Tail.Overlay.DriverContext[0],
                };

548
                WINE_UNIX_CALL(unix_usb_cancel_transfer, &params);
549 550 551 552 553 554 555 556 557 558 559 560
            }
            LeaveCriticalSection(&wineusb_cs);

            return STATUS_SUCCESS;
        }

        case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
        case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
        case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
        case URB_FUNCTION_SELECT_CONFIGURATION:
        case URB_FUNCTION_VENDOR_INTERFACE:
        {
561 562 563 564 565 566
            struct usb_submit_urb_params params =
            {
                .device = device->unix_device,
                .irp = irp,
            };

567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
            switch (urb->UrbHeader.Function)
            {
                case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
                {
                    struct _URB_BULK_OR_INTERRUPT_TRANSFER *req = &urb->UrbBulkOrInterruptTransfer;
                    if (req->TransferBufferMDL)
                        params.transfer_buffer = MmGetSystemAddressForMdlSafe(req->TransferBufferMDL, NormalPagePriority);
                    else
                        params.transfer_buffer = req->TransferBuffer;
                    break;
                }

                case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
                {
                    struct _URB_CONTROL_DESCRIPTOR_REQUEST *req = &urb->UrbControlDescriptorRequest;
                    if (req->TransferBufferMDL)
                        params.transfer_buffer = MmGetSystemAddressForMdlSafe(req->TransferBufferMDL, NormalPagePriority);
                    else
                        params.transfer_buffer = req->TransferBuffer;
                    break;
                }

                case URB_FUNCTION_VENDOR_INTERFACE:
                {
                    struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *req = &urb->UrbControlVendorClassRequest;
                    if (req->TransferBufferMDL)
                        params.transfer_buffer = MmGetSystemAddressForMdlSafe(req->TransferBufferMDL, NormalPagePriority);
                    else
                        params.transfer_buffer = req->TransferBuffer;
                    break;
                }
            }

600 601 602 603 604
            /* Hold the wineusb lock while submitting and queuing, and
             * similarly hold it in complete_irp(). That way, if libusb reports
             * completion between submitting and queuing, we won't try to
             * dequeue the IRP until it's actually been queued. */
            EnterCriticalSection(&wineusb_cs);
605
            status = WINE_UNIX_CALL(unix_usb_submit_urb, &params);
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
            if (status == STATUS_PENDING)
            {
                IoMarkIrpPending(irp);
                InsertTailList(&device->irp_list, &irp->Tail.Overlay.ListEntry);
            }
            LeaveCriticalSection(&wineusb_cs);

            return status;
        }

        default:
            FIXME("Unhandled function %#x.\n", urb->UrbHeader.Function);
    }

    return STATUS_NOT_IMPLEMENTED;
}

623 624 625 626 627 628
static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device_obj, IRP *irp)
{
    IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
    ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
    struct usb_device *device = device_obj->DeviceExtension;
    NTSTATUS status = STATUS_NOT_IMPLEMENTED;
629
    BOOL removed;
630

631
    TRACE("device_obj %p, irp %p, code %#lx.\n", device_obj, irp, code);
632

633 634 635 636 637 638 639 640 641 642 643
    EnterCriticalSection(&wineusb_cs);
    removed = device->removed;
    LeaveCriticalSection(&wineusb_cs);

    if (removed)
    {
        irp->IoStatus.Status = STATUS_DELETE_PENDING;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
        return STATUS_DELETE_PENDING;
    }

644 645 646 647 648 649 650
    switch (code)
    {
        case IOCTL_INTERNAL_USB_SUBMIT_URB:
            status = usb_submit_urb(device, irp);
            break;

        default:
651
            FIXME("Unhandled ioctl %#lx (device %#lx, access %#lx, function %#lx, method %#lx).\n",
652 653 654
                    code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
    }

655
    if (status != STATUS_PENDING)
656 657 658 659 660 661 662
    {
        irp->IoStatus.Status = status;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
    }
    return status;
}

663 664 665 666 667 668 669 670
static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *pdo)
{
    NTSTATUS ret;

    TRACE("driver %p, pdo %p.\n", driver, pdo);

    if ((ret = IoCreateDevice(driver, 0, NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &bus_fdo)))
    {
671
        ERR("Failed to create FDO, status %#lx.\n", ret);
672 673 674 675 676 677 678 679 680 681
        return ret;
    }

    IoAttachDeviceToDeviceStack(bus_fdo, pdo);
    bus_pdo = pdo;
    bus_fdo->Flags &= ~DO_DEVICE_INITIALIZING;

    return STATUS_SUCCESS;
}

682 683 684 685 686 687
static void WINAPI driver_unload(DRIVER_OBJECT *driver)
{
}

NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path)
{
688
    NTSTATUS status;
689 690 691

    TRACE("driver %p, path %s.\n", driver, debugstr_w(path->Buffer));

692
    if ((status = __wine_init_unix_call()))
693
    {
694
        ERR("Failed to initialize Unix library, status %#lx.\n", status);
695 696 697
        return status;
    }

698 699
    driver_obj = driver;

700
    driver->DriverExtension->AddDevice = driver_add_device;
701
    driver->DriverUnload = driver_unload;
702
    driver->MajorFunction[IRP_MJ_PNP] = driver_pnp;
703
    driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = driver_internal_ioctl;
704 705 706

    return STATUS_SUCCESS;
}