/** * Create a filedisk PDO filled with the given disk parameters. * * @v MediaType The media type for the filedisk. * @ret WV_SP_FILEDISK_T Points to the new filedisk, or NULL. * * Returns NULL if the PDO cannot be created. */ WV_SP_FILEDISK_T STDCALL WvFilediskCreatePdo( IN WVL_E_DISK_MEDIA_TYPE MediaType ) { NTSTATUS status; WV_SP_FILEDISK_T filedisk; PDEVICE_OBJECT pdo; DBG("Creating filedisk PDO...\n"); /* Create the disk PDO. */ status = WvlDiskCreatePdo( WvDriverObj, sizeof *filedisk, MediaType, &pdo ); if (!NT_SUCCESS(status)) { WvlError("WvlDiskCreatePdo", status); goto err_pdo; } /* Initialize. */ filedisk = pdo->DeviceExtension; RtlZeroMemory(filedisk, sizeof *filedisk); WvlDiskInit(filedisk->disk); WvDevInit(filedisk->Dev); filedisk->Dev->Ops.Free = WvFilediskFree_; filedisk->Dev->ext = filedisk->disk; filedisk->disk->disk_ops.Io = WvFilediskIo_; filedisk->disk->disk_ops.UnitNum = WvFilediskUnitNum_; filedisk->disk->disk_ops.PnpQueryId = WvFilediskPnpQueryId_; filedisk->disk->disk_ops.PnpQueryDevText = WvDiskPnpQueryDevText; filedisk->disk->ext = filedisk; filedisk->disk->DriverObj = WvDriverObj; filedisk->disk->DenyPageFile = TRUE; InitializeListHead(filedisk->Irps); KeInitializeSpinLock(filedisk->IrpsLock); /* Start the thread. */ filedisk->Thread->Main.Func = WvFilediskThread_; status = WvlThreadStart(filedisk->Thread); if (!NT_SUCCESS(status)) { DBG("Couldn't create thread!\n"); goto err_thread; } /* Set associations for the PDO, device, disk. */ WvDevForDevObj(pdo, filedisk->Dev); WvDevSetIrpHandler(pdo, WvFilediskIrpDispatch); filedisk->Dev->Self = pdo; /* Some device parameters. */ pdo->Flags |= DO_DIRECT_IO; /* FIXME? */ pdo->Flags |= DO_POWER_INRUSH; /* FIXME? */ DBG("New PDO: %p\n", pdo); return filedisk; WvlThreadSendStopAndWait(filedisk->Thread); err_thread: IoDeleteDevice(pdo); err_pdo: return NULL; }
/* Produce a dummy PDO node on the main bus. Internal */ static NTSTATUS STDCALL WvDummyAdd_( IN WV_SP_DUMMY_IDS DummyIds, IN PDEVICE_OBJECT * Pdo ) { NTSTATUS status; PDEVICE_OBJECT pdo = NULL; WV_SP_DEV_T dev; WV_SP_DUMMY_IDS new_dummy_ids; status = IoCreateDevice( WvDriverObj, sizeof (WV_S_DEV_EXT), NULL, DummyIds->DevType, DummyIds->DevCharacteristics, FALSE, &pdo ); if (!NT_SUCCESS(status) || !pdo) { DBG("Couldn't create dummy device.\n"); status = STATUS_INSUFFICIENT_RESOURCES; goto err_create_pdo; } dev = wv_malloc(sizeof *dev); if (!dev) { DBG("Couldn't allocate dummy device.\n"); status = STATUS_INSUFFICIENT_RESOURCES; goto err_dev; } new_dummy_ids = wv_malloc(DummyIds->Len); if (!new_dummy_ids) { DBG("Couldn't allocate dummy IDs.\n"); status = STATUS_INSUFFICIENT_RESOURCES; goto err_dummy_ids; } /* Copy the IDs' offsets and lengths. */ RtlCopyMemory(new_dummy_ids, DummyIds, DummyIds->Len); /* Ok! */ WvDevInit(dev); dev->ext = new_dummy_ids; /* TODO: Implement a dummy free. Leaking. */ dev->Self = pdo; /* Optionally fill the caller's PDO pointer. */ if (Pdo) *Pdo = pdo; WvDevForDevObj(pdo, dev); WvDevSetIrpHandler(pdo, WvDummyIrpDispatch); WvlBusInitNode(&dev->BusNode, pdo); /* Associate the parent bus. */ dev->Parent = WvBus.Fdo; /* Add the new PDO device to the bus' list of children. */ WvlBusAddNode(&WvBus, &dev->BusNode); pdo->Flags &= ~DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; wv_free(new_dummy_ids); err_dummy_ids: wv_free(dev); err_dev: IoDeleteDevice(pdo); err_create_pdo: return status; }