/* Find the path to the backend associated with @sf. The backend path remains correct as long as @token remains extant. The caller must XmFreeMemory() the returned string. Returns NULL on error. */ static char * get_backend_path(struct scsifilt *sf, SUSPEND_TOKEN token) { char *res; char *res_nul; NTSTATUS stat; size_t s; UNREFERENCED_PARAMETER(token); stat = xenbus_read_bin(XBT_NIL, sf->frontend_path, "backend", &res, &s); if (!NT_SUCCESS(stat)) { TraceWarning(("%x reading backend path.\n", stat)); return NULL; } res_nul = XmAllocateMemory(s + 1); if (!res_nul) { TraceWarning(("Can't get %d bytes for backend path\n", s)); XmFreeMemory(res); return NULL; } memcpy(res_nul, res, s); res_nul[s] = 0; XmFreeMemory(res); return res_nul; }
static NTSTATUS redirect_irp_completion(PDEVICE_OBJECT dev_obj, PIRP irp, PVOID ctxt) { IO_STACK_LOCATION *const isl = IoGetCurrentIrpStackLocation(irp); struct scsifilt *const sf = get_scsifilt(dev_obj); SCSI_REQUEST_BLOCK *const new_srb = isl->Parameters.Scsi.Srb; SCSI_REQUEST_BLOCK *const srb = new_srb->OriginalRequest; MDL *const mdl = irp->MdlAddress; void *const buf = new_srb->DataBuffer; UNREFERENCED_PARAMETER(ctxt); srb->SrbStatus = new_srb->SrbStatus; srb->ScsiStatus = new_srb->ScsiStatus; memcpy(srb->DataBuffer, buf, srb->DataTransferLength); IoFreeIrp(irp); IoFreeMdl(mdl); ExFreePool(buf); XmFreeMemory(new_srb); queue_srb_for_completion(sf, srb); return STATUS_MORE_PROCESSING_REQUIRED; }
ULONG XenLowerInterfaceVersion( PXEN_LOWER XenLower) { NTSTATUS status; PCHAR vstr; int version; vstr = XenLowerReadXenstoreValue(XenLower->BackendPath, "version"); if (vstr == NULL) { TraceError((__FUNCTION__\ ": XenLowerReadXenstoreValue() failed to return the vusb version.\n")); return 0; } sscanf_s(vstr, "%d", &version); XmFreeMemory(vstr); // Need to now write the version we support to the frontend status = xenbus_printf(XBT_NIL, XenLower->FrontendPath, "version", "%d", XEN_LOWER_INTERFACE_VERSION); if (!NT_SUCCESS(status)) { TraceError((__FUNCTION__\ ": xenbus_printf(frontend/version) failed.\n")); return 0; } TraceInfo((__FUNCTION__ ": Read backend version: %d - Wrote frontend version: %d\n", version, XEN_LOWER_INTERFACE_VERSION)); return (ULONG)version; }
/* Write a grant ref and ec port to xenstore in a transaction for whatever * your pThing is. Also some non-transaction read/write stuff. */ static NTSTATUS GrantAndEventChannelInATransaction(CHAR *pFrontendPath, struct THING *pThing) { NTSTATUS Status; CHAR *pMyData; xenbus_transaction_t Xbt; do { xenbus_transaction_start(&Xbt); xenbus_write_grant_ref(Xbt, pFrontendPath, "ring-ref", pThing->RingGrantRef); xenbus_write_evtchn_port(Xbt, pFrontendPath, "event-channel", pThing->EvtchnPort); Status = xenbus_transaction_end(Xbt, 0); } while (Status == STATUS_RETRY); if (Status != STATUS_SUCCESS) { DbgPrint("Failed to end transaction, 0x%08x.\n", Status); /* Handle failure */ } /* A write and read w/o a transaction */ xenbus_write(XBT_NIL, "drivers/mydriver", "1.2.3.4"); Status = xenbus_read(XBT_NIL, "drivers/mydriver/mydata", &pMyData); if (NT_SUCCESS(Status)) { DbgPrint("Read MyData: %s\n", pMyData); XmFreeMemory(pMyData); } /* ... */ }
struct xm_thread * XmSpawnThread(NTSTATUS (*cb)(struct xm_thread *xt, void *d), void *d) { struct xm_thread *work; NTSTATUS stat; HANDLE tmpHandle; work = XmAllocateMemory(sizeof(*work)); if (!work) return NULL; work->exit = FALSE; KeInitializeEvent(&work->event, NotificationEvent, FALSE); work->cb = cb; work->data = d; stat = PsCreateSystemThread(&tmpHandle, THREAD_ALL_ACCESS, NULL, INVALID_HANDLE_VALUE, NULL, xm_thread_func, work); if (!NT_SUCCESS(stat)) { XmFreeMemory(work); return NULL; } stat = ObReferenceObjectByHandle(tmpHandle, SYNCHRONIZE, NULL, KernelMode, &work->thread, NULL); ZwClose(tmpHandle); if (!NT_SUCCESS(stat)) { /* We can't reliably kill the thread in this case, and therefore can't release memory. Instruct it to exit soon and hope for the best. */ work->exit = TRUE; KeSetEvent(&work->event, IO_NO_INCREMENT, FALSE); return NULL; } return work; }
BOOLEAN XenLowerBackendInit( PXEN_LOWER XenLower) { PCHAR path; NTSTATUS status; // Note this is split from the XenLowerInit so it can be called on the resume // path in case backend values change. XXX_TODO("--XT-- All the backend path handling assumes dom0 is the backend, this will change for device domains") // XXX TODO all the backend path handling assumes dom0 is the backend. This will // not necessarily be true with device domains. The changes to support this go // beyond this module though. path = XenLowerReadXenstoreValue(XenLower->FrontendPath, "backend"); if (path == NULL) { TraceError((__FUNCTION__ ": XenLowerReadXenstoreValue() failed to return the back end path, fatal.\n")); return FALSE; } status = RtlStringCchCopyA(XenLower->BackendPath, sizeof(XenLower->BackendPath), path); XmFreeMemory(path); if (status != STATUS_SUCCESS) { XenLower->BackendPath[0] = 0; TraceError((__FUNCTION__ ": Failed to copy back end path - status: 0x%x\n", status)); return FALSE; } status = xenbus_read_domain_id(XBT_NIL, XenLower->FrontendPath, "backend-id", &XenLower->BackendDomid); if (!NT_SUCCESS(status)) { TraceWarning((__FUNCTION__ ": Failed to read backend id from %s (%x), setting to dom0\n", XenLower->FrontendPath, status)); XenLower->BackendDomid = DOMAIN_ID_0(); } // XXX TODO for now we only support a dom0 backend so check that here. Later // when we support a device domain for vusb, other domids will be fine. XXX_TODO("--XT-- For now we only support a dom0 backend so check that here"); if (unwrap_DOMAIN_ID(XenLower->BackendDomid) != unwrap_DOMAIN_ID(DOMAIN_ID_0())) { TraceError((XENTARGET ": cannot connect to backend Domid: %d, only dom0 supported currently\n", XenLower->BackendDomid)); return FALSE; } TraceInfo((__FUNCTION__ ": XenLower initialized - FrontendPath: %s BackendPath: %s BackendDomid: %d\n", XenLower->FrontendPath, XenLower->BackendPath, unwrap_DOMAIN_ID(XenLower->BackendDomid))); return TRUE; }
static PCHAR XenLowerReadXenstoreValue( PCHAR Path, PCHAR Value) { ULONG plen, vlen; PCHAR path; PCHAR res = NULL; NTSTATUS status; plen = (ULONG)strlen(Path); vlen = (ULONG)strlen(Value); path = (PCHAR)XmAllocateMemory(plen + vlen + 2); if (path == NULL) { return NULL; } memcpy(path, Path, plen); path[plen] = '/'; memcpy(path + plen + 1, Value, vlen + 1); status = xenbus_read(XBT_NIL, path, &res); XmFreeMemory(path); if (!NT_SUCCESS(status)) { return NULL; } return res; }
void XmKillThread(struct xm_thread *t) { if (!t) return; TraceDebug (("Killing thread %p.\n", t)); XM_ASSERT(KeGetCurrentThread() != t->thread); t->exit = TRUE; KeSetEvent(&t->event, IO_NO_INCREMENT, FALSE); KeWaitForSingleObject(t->thread, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(t->thread); XmFreeMemory(t); }
BOOLEAN XenLowerInit( PXEN_LOWER XenLower, PVOID XenUpper, PDEVICE_OBJECT Pdo) { PCHAR path; NTSTATUS status; XenLower->XenUpper = XenUpper; XenLower->Pdo = Pdo; // // Wait for xenbus to come up. SMP guests sometimes try and // initialise xennet and xenvbd in parallel when they come back // from hibernation, and that causes problems. // if (!xenbus_await_initialisation()) { TraceError((__FUNCTION__ ": xenbus_await_initialisation() failed?\n")); return FALSE; } path = xenbus_find_frontend(Pdo); if (path == NULL) { TraceError((__FUNCTION__ ": xenbus_find_frontend() failed to return the front end path, fatal.\n")); return FALSE; } status = RtlStringCchCopyA(XenLower->FrontendPath, sizeof(XenLower->FrontendPath), path); XmFreeMemory(path); if (status != STATUS_SUCCESS) { XenLower->FrontendPath[0] = 0; TraceError((__FUNCTION__ ": Failed to copy front end path - status: 0x%x\n", status)); return FALSE; } return TRUE; }
static NTSTATUS XenWorkItemDispatch( IN struct xm_thread *pSelf, IN VOID *Argument ) { KIRQL Irql; UNREFERENCED_PARAMETER(Argument); while (XmThreadWait(pSelf) >= 0) { Irql = acquire_irqsafe_lock(&WorkItemDispatchLock); while (!IsListEmpty(&PendingWorkItems)) { PLIST_ENTRY Head; XEN_WORKITEM *Item; Head = RemoveHeadList(&PendingWorkItems); Item = CurrentItem = CONTAINING_RECORD(Head, XEN_WORKITEM, List); release_irqsafe_lock(&WorkItemDispatchLock, Irql); XM_ASSERT(CurrentItem->Magic == WORKITEM_MAGIC); KeQuerySystemTime(&Item->Start); TraceVerbose(("%s: invoking '%s'\n", __FUNCTION__, CurrentItem->Name)); CurrentItem->Work(CurrentItem->Context); Irql = acquire_irqsafe_lock(&WorkItemDispatchLock); CurrentItem = NULL; release_irqsafe_lock(&WorkItemDispatchLock, Irql); XmFreeMemory(Item); Irql = acquire_irqsafe_lock(&WorkItemDispatchLock); } release_irqsafe_lock(&WorkItemDispatchLock, Irql); } TraceWarning(("%s: terminating.\n", __FUNCTION__)); return STATUS_SUCCESS; }
BOOLEAN XenLowerGetOnline( PVOID Context) { PXEN_LOWER XenLower = (PXEN_LOWER)Context; PCHAR sstr; int state; sstr = XenLowerReadXenstoreValue(XenLower->BackendPath, "online"); if (sstr == NULL) { TraceError((__FUNCTION__ ": XenLowerReadXenstoreValue() failed to return the back end state.\n")); return FALSE; } sscanf_s(sstr, "%d", &state); XmFreeMemory(sstr); return (state == 1); }
ULONG XenLowerGetBackendState( PVOID Context) { PXEN_LOWER XenLower = (PXEN_LOWER)Context; PCHAR sstr; int state; sstr = XenLowerReadXenstoreValue(XenLower->BackendPath, "state"); if (sstr == NULL) { TraceError((__FUNCTION__ ": XenLowerReadXenstoreValue() failed to return the back end state.\n")); return XenbusStateUnknown; } sscanf_s(sstr, "%d", &state); XmFreeMemory(sstr); return (ULONG)state; }
static NTSTATUS NTAPI V4vDispatchPnP(PDEVICE_OBJECT fdo, PIRP irp) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION isl = IoGetCurrentIrpStackLocation(irp); PXENV4V_EXTENSION pde = V4vGetDeviceExtension(fdo); KEVENT kev; TraceVerbose(("====> '%s'.\n", __FUNCTION__)); TraceVerbose((" =PnP= 0x%x\n", isl->MinorFunction)); status = IoAcquireRemoveLock(&pde->removeLock, irp); if (!NT_SUCCESS(status)) { TraceError(("failed to acquire IO lock - error: 0x%x\n", status)); return V4vSimpleCompleteIrp(irp, status); } switch (isl->MinorFunction) { case IRP_MN_START_DEVICE: KeInitializeEvent(&kev, NotificationEvent, FALSE); // Send the start down and wait for it to complete IoCopyCurrentIrpStackLocationToNext(irp); IoSetCompletionRoutine(irp, V4vStartDeviceIoCompletion, &kev, TRUE, TRUE, TRUE); status = IoCallDriver(pde->ldo, irp); if (status == STATUS_PENDING) { // Wait for everything underneath us to complete TraceVerbose(("Device start waiting for lower device.\n")); KeWaitForSingleObject(&kev, Executive, KernelMode, FALSE, NULL); TraceVerbose(("Device start wait finished.\n")); } status = irp->IoStatus.Status; if (!NT_SUCCESS(status)) { TraceError(("Failed to start lower drivers: %x.\n", status)); IoCompleteRequest(irp, IO_NO_INCREMENT); break; } status = STATUS_SUCCESS; // Connect our interrupt (ec). status = V4vInitializeEventChannel(fdo); if (NT_SUCCESS(status)) { InterlockedExchange(&pde->state, XENV4V_DEV_STARTED); } else { TraceError(("failed to initialize event channel - error: 0x%x\n", status)); } irp->IoStatus.Status = status; IoCompleteRequest(irp, IO_NO_INCREMENT); break; case IRP_MN_STOP_DEVICE: // Stop our device's IO processing V4vStopDevice(fdo, pde); // Pass it down irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(irp); status = IoCallDriver(pde->ldo, irp); break; case IRP_MN_REMOVE_DEVICE: // Stop our device's IO processing V4vStopDevice(fdo, pde); // Cleanup anything here that locks for IO IoReleaseRemoveLockAndWait(&pde->removeLock, irp); // Pass it down first IoSkipCurrentIrpStackLocation(irp); status = IoCallDriver(pde->ldo, irp); // Then detach and cleanup our device xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CLOSED); IoDetachDevice(pde->ldo); ExDeleteNPagedLookasideList(&pde->destLookasideList); XmFreeMemory(pde->frontendPath); IoDeleteSymbolicLink(&pde->symbolicLink); IoDeleteDevice(fdo); InterlockedAnd(&g_deviceCreated, 0); return status; default: // Pass it down TraceVerbose(("IRP_MJ_PNP MinorFunction %d passed down\n", isl->MinorFunction)); IoSkipCurrentIrpStackLocation(irp); status = IoCallDriver(pde->ldo, irp); }; // Everybody but REMOVE IoReleaseRemoveLock(&pde->removeLock, irp); TraceVerbose(("<==== '%s'.\n", __FUNCTION__)); return status; }
/* We've bound the scsifilt instance to a xenvbd instance, and we've disconnected xenvbd from the shared ring. Connect scsifilt. */ NTSTATUS connect_scsifilt_with_token(struct scsifilt *sf, SUSPEND_TOKEN token) { XENBUS_STATE state; blkif_sring_t *ring_shared; NTSTATUS status; KIRQL irql; if (sf->backend_path != NULL) { TraceVerbose(("Releasing old backend path (%p)\n", sf->backend_path)); XmFreeMemory(sf->backend_path); sf->backend_path = NULL; } if (sf->ring_shared != NULL) { TraceVerbose(("Releasing old shared ring (%p)\n", sf->ring_shared)); XmFreeMemory(sf->ring_shared); sf->ring_shared = NULL; sf->ring.sring = NULL; } find_backend_handle(sf); status = STATUS_UNSUCCESSFUL; sf->backend_path = get_backend_path(sf, token); if (sf->backend_path == NULL) goto fail1; sf->target_resume(sf->target_id, token); if (sf->stopped) { sf->target_start(sf->target_id, sf->backend_path, token); sf->stopped = FALSE; } state = XenbusWaitForBackendStateChange(sf->backend_path, null_XENBUS_STATE(), NULL, token); if (!same_XENBUS_STATE(state, XENBUS_STATE_INITWAIT)) goto fail2; probe_backend_capabilities(sf); status = STATUS_NO_MEMORY; ring_shared = XmAllocateZeroedMemory(PAGE_SIZE << sf->ring_order); if (ring_shared == NULL) goto fail3; KeAcquireSpinLock(&sf->ring_lock, &irql); sf->ring_shared = ring_shared; SHARED_RING_INIT(sf->ring_shared); FRONT_RING_INIT(&sf->ring, sf->ring_shared, PAGE_SIZE << sf->ring_order); KeReleaseSpinLock(&sf->ring_lock, irql); grant_ring(sf); status = open_evtchn(sf); if (!NT_SUCCESS(status)) goto fail4; do { xenbus_transaction_t xbt; xenbus_transaction_start(&xbt); xenbus_write_evtchn_port(xbt, sf->frontend_path, "event-channel", sf->evtchn_port); if (sf->single_page) { XM_ASSERT3U(sf->ring_order, ==, 0); TraceNotice(("%s: using single page handshake\n", sf->frontend_path)); /* single page handshake */ xenbus_write_grant_ref(xbt, sf->frontend_path, "ring-ref", sf->ring_gref[0]); } else { int i; TraceNotice(("%s: using multi-page handshake\n", sf->frontend_path)); xenbus_printf(xbt, sf->frontend_path, "ring-page-order", "%u", sf->ring_order); for (i = 0; i < (1 << sf->ring_order); i++) { char buffer[10]; Xmsnprintf(buffer, sizeof(buffer), "ring-ref%1u", i); xenbus_write_grant_ref(xbt, sf->frontend_path, buffer, sf->ring_gref[i]); } } xenbus_printf(xbt, sf->frontend_path, "protocol", "x86_32-abi"); xenbus_write_feature_flag(xbt, sf->frontend_path, "feature-surprise-remove", TRUE); xenbus_write_feature_flag(xbt, sf->frontend_path, "feature-online-resize", TRUE); xenbus_change_state(xbt, sf->frontend_path, "state", XENBUS_STATE_INITIALISED); status = xenbus_transaction_end(xbt, 0); } while (status == STATUS_RETRY);
/* srb is kind of half const here. We never modify it directly, but it will obviously get modified when it completes. */ static void allocate_irp_and_resubmit_srb(struct scsifilt *sf, SCSI_REQUEST_BLOCK *srb_) { const SCSI_REQUEST_BLOCK *const srb = srb_; PIRP irp; PIO_STACK_LOCATION isl; PVOID buf; PMDL mdl; PSCSI_REQUEST_BLOCK new_srb; irp = NULL; mdl = NULL; new_srb = NULL; buf = ExAllocatePoolWithTag(NonPagedPool, srb->DataTransferLength, 'ssrx'); if (!buf) goto err; memcpy(buf, srb->DataBuffer, srb->DataTransferLength); new_srb = XmAllocateZeroedMemory(sizeof(*new_srb)); if (!new_srb) goto err; new_srb->Length = sizeof(*new_srb); new_srb->Function = srb->Function; XM_ASSERT3U(new_srb->Function, ==, SRB_FUNCTION_EXECUTE_SCSI); new_srb->SrbFlags = srb->SrbFlags; new_srb->PathId = srb->PathId; new_srb->TargetId = srb->TargetId; new_srb->Lun = srb->Lun; new_srb->QueueTag = srb->QueueTag; new_srb->QueueAction = srb->QueueAction; new_srb->DataTransferLength = srb->DataTransferLength; new_srb->DataBuffer = buf; new_srb->OriginalRequest = (PVOID)srb; new_srb->CdbLength = srb->CdbLength; memcpy(new_srb->Cdb, srb->Cdb, srb->CdbLength); irp = IoAllocateIrp(2, FALSE); if (!irp) goto err; mdl = IoAllocateMdl(buf, new_srb->DataTransferLength, FALSE, FALSE, irp); if (!mdl) goto err; MmBuildMdlForNonPagedPool(mdl); IoSetNextIrpStackLocation(irp); isl = IoGetCurrentIrpStackLocation(irp); isl->Parameters.Scsi.Srb = new_srb; isl->DeviceObject = sf->fdo; IoSetCompletionRoutine(irp, redirect_irp_completion, NULL, TRUE, TRUE, TRUE); IoSetNextIrpStackLocation(irp); isl = IoGetCurrentIrpStackLocation(irp); isl->MajorFunction = IRP_MJ_SCSI; isl->MinorFunction = 0; isl->Parameters.Scsi.Srb = new_srb; isl->DeviceObject = sf->fdo; filter_process_irp(sf, irp, new_srb); return; err: TraceWarning(("Failed to set up redirected SRB\n")); if (irp) IoFreeIrp(irp); if (mdl) IoFreeMdl(mdl); if (buf) ExFreePool(buf); if (new_srb) XmFreeMemory(new_srb); queue_srb_for_error(sf, (PSCSI_REQUEST_BLOCK)srb); }
NDIS_STATUS MiniportInitialize ( IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_HANDLE MiniportDriverContext, IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters ) { PADAPTER adapter = NULL; NDIS_STATUS ndisStatus; PCHAR path; PDEVICE_OBJECT pdo; PCHAR xenbusPath = NULL; int i; UNREFERENCED_PARAMETER(MiniportDriverContext); UNREFERENCED_PARAMETER(MiniportInitParameters); TraceVerbose(("====> '%s'.\n", __FUNCTION__)); // // Wait for xenbus to come up. SMP guests sometimes try and // initialise xennet and xenvbd in parallel when they come back // from hibernation, and that causes problems. // if (!xenbus_await_initialisation()) { ndisStatus = NDIS_STATUS_DEVICE_FAILED; goto exit; } // // 8021P support is disabled by default. // It can be turned on by specifying the appropriate PV boot option. // if (XenPVFeatureEnabled(DEBUG_NIC_8021_P)) { XennetMacOptions |= NDIS_MAC_OPTION_8021P_PRIORITY; } xenbus_write(XBT_NIL, "drivers/xenwnet", XENNET_VERSION); NdisMGetDeviceProperty(MiniportAdapterHandle, &pdo, NULL, NULL, NULL, NULL); xenbusPath = xenbus_find_frontend(pdo); if (!xenbusPath) { ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND; goto exit; } TraceNotice(("Found '%s' frontend.\n", xenbusPath)); adapter = XmAllocateZeroedMemory(sizeof(ADAPTER)); if (adapter == NULL) { ndisStatus = NDIS_STATUS_RESOURCES; goto exit; } path = xenbusPath; xenbusPath = NULL; i = 0; do { ndisStatus = AdapterInitialize(adapter, MiniportAdapterHandle, path); if (ndisStatus != NDIS_STATUS_SUCCESS) { TraceWarning (("Waiting for backend...\n")); NdisMSleep (1000000); // 1 sec } } while ((ndisStatus != NDIS_STATUS_SUCCESS) && (++i < 30)); if (ndisStatus != NDIS_STATUS_SUCCESS) { goto exit; } exit: if (ndisStatus != NDIS_STATUS_SUCCESS) { if (adapter) { XmFreeMemory(adapter->BackendPath); adapter->BackendPath = NULL; AdapterDelete(&adapter); } if (xenbusPath) { XmFreeMemory(xenbusPath); } } TraceVerbose(("<==== '%s'.\n", __FUNCTION__)); return ndisStatus; }
static NTSTATUS V4vAddDevice(PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING deviceName; PDEVICE_OBJECT fdo = NULL; PXENV4V_EXTENSION pde = NULL; LONG val; BOOLEAN symlink = FALSE; LARGE_INTEGER seed; WCHAR *szSddl = NULL; UNICODE_STRING sddlString; CHAR *szFpath = NULL; TraceVerbose(("====> '%s'.\n", __FUNCTION__)); // We only allow one instance of this device type. If more than on pdo is created we need val = InterlockedCompareExchange(&g_deviceCreated, 1, 0); if (val != 0) { TraceWarning(("cannot instantiate more that one v4v device node.\n")); return STATUS_UNSUCCESSFUL; } do { // Create our device RtlInitUnicodeString(&deviceName, V4V_DEVICE_NAME); szSddl = g_win5Sddl; RtlInitUnicodeString(&sddlString, szSddl); status = IoCreateDeviceSecure(driverObject, sizeof(XENV4V_EXTENSION), &deviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &sddlString, (LPCGUID)&GUID_SD_XENV4V_CONTROL_OBJECT, &fdo); if (!NT_SUCCESS(status)) { TraceError(("failed to create device object - error: 0x%x\n", status)); fdo = NULL; break; } pde = (PXENV4V_EXTENSION)fdo->DeviceExtension; RtlZeroMemory(pde, sizeof(XENV4V_EXTENSION)); RtlStringCchCopyW(pde->symbolicLinkText, XENV4V_SYM_NAME_LEN, V4V_SYMBOLIC_NAME); RtlInitUnicodeString(&pde->symbolicLink, pde->symbolicLinkText); // Create our symbolic link status = IoCreateSymbolicLink(&pde->symbolicLink, &deviceName); if (!NT_SUCCESS(status)) { TraceError(("failed to create symbolic - error: 0x%x\n", status)); break; } symlink = TRUE; // Get our xenstore path szFpath = xenbus_find_frontend(pdo); if (szFpath == NULL) { status = STATUS_NO_SUCH_DEVICE; TraceError(("failed to locate XenStore front end path\n")); break; } // Setup the extension pde->magic = XENV4V_MAGIC; pde->pdo = pdo; pde->fdo = fdo; IoInitializeRemoveLock(&pde->removeLock, 'v4vx', 0, 0); pde->frontendPath = szFpath; szFpath = NULL; pde->state = XENV4V_DEV_STOPPED; // wait for start pde->lastPoState = PowerSystemWorking; pde->virqPort = null_EVTCHN_PORT(); KeInitializeDpc(&pde->virqDpc, V4vVirqNotifyDpc, fdo); KeInitializeSpinLock(&pde->virqLock); KeInitializeSpinLock(&pde->dpcLock); KeInitializeTimerEx(&pde->timer, NotificationTimer); KeInitializeDpc(&pde->timerDpc, V4vConnectTimerDpc, fdo); KeInitializeSpinLock(&pde->timerLock); pde->timerCounter = 0; InitializeListHead(&pde->contextList); KeInitializeSpinLock(&pde->contextLock); pde->contextCount = 0; InitializeListHead(&pde->ringList); KeInitializeSpinLock(&pde->ringLock); InitializeListHead(&pde->pendingIrpQueue); pde->pendingIrpCount = 0; KeInitializeSpinLock(&pde->queueLock); IoCsqInitializeEx(&pde->csqObject, V4vCsqInsertIrpEx, V4vCsqRemoveIrp, V4vCsqPeekNextIrp, V4vCsqAcquireLock, V4vCsqReleaseLock, V4vCsqCompleteCanceledIrp); InitializeListHead(&pde->destList); pde->destCount = 0; ExInitializeNPagedLookasideList(&pde->destLookasideList, NULL, NULL, 0, sizeof(XENV4V_DESTINATION), XENV4V_TAG, 0); KeQueryTickCount(&seed); pde->seed = seed.u.LowPart; // Now attach us to the stack pde->ldo = IoAttachDeviceToDeviceStack(fdo, pdo); if (pde->ldo == NULL) { TraceError(("failed to attach device to stack - error: 0x%x\n", status)); status = STATUS_NO_SUCH_DEVICE; break; } // Use direct IO and let the IO manager directly map user buffers; clear the init flag fdo->Flags |= DO_DIRECT_IO; fdo->Flags &= ~DO_DEVICE_INITIALIZING; // Made it here, go to connected state to be consistent xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CONNECTED); } while (FALSE); if (!NT_SUCCESS(status)) { if (fdo != NULL) { if ((pde != NULL)&&(pde->ldo != NULL)) { IoDetachDevice(pde->ldo); } if (szFpath != NULL) { XmFreeMemory(szFpath); } if (symlink) { IoDeleteSymbolicLink(&pde->symbolicLink); } IoDeleteDevice(fdo); } } TraceVerbose(("<==== '%s'.\n", __FUNCTION__)); return status; }