97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync/* $Id$ */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync/** @file
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * Windows Driver R0 Tooling.
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync/*
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * Copyright (C) 2011 Oracle Corporation
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync *
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * available from http://www.virtualbox.org. This file is free software;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * you can redistribute it and/or modify it under the terms of the GNU
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * General Public License (GPL) as published by the Free Software
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#include "VBoxDrvTool.h"
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#include <iprt/assert.h>
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync#include <VBox/log.h>
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync#include "../../../win/VBoxDbgLog.h"
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#define VBOXDRVTOOL_MEMTAG 'TDBV'
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic PVOID vboxDrvToolMemAlloc(SIZE_T cbBytes)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync PVOID pvMem = ExAllocatePoolWithTag(NonPagedPool, cbBytes, VBOXDRVTOOL_MEMTAG);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync Assert(pvMem);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return pvMem;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic PVOID vboxDrvToolMemAllocZ(SIZE_T cbBytes)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync PVOID pvMem = vboxDrvToolMemAlloc(cbBytes);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync if (pvMem)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync RtlZeroMemory(pvMem, cbBytes);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync }
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return pvMem;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic VOID vboxDrvToolMemFree(PVOID pvMem)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ExFreePoolWithTag(pvMem, VBOXDRVTOOL_MEMTAG);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegOpenKeyU(OUT PHANDLE phKey, IN PUNICODE_STRING pName, IN ACCESS_MASK fAccess)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync OBJECT_ATTRIBUTES ObjAttr;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync InitializeObjectAttributes(&ObjAttr, pName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return ZwOpenKey(phKey, fAccess, &ObjAttr);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync UNICODE_STRING RtlStr;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync RtlInitUnicodeString(&RtlStr, pName);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return VBoxDrvToolRegOpenKeyU(phKey, &RtlStr, fAccess);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegCloseKey(IN HANDLE hKey)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return ZwClose(hKey);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PULONG pDword)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync struct
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KEY_VALUE_PARTIAL_INFORMATION Info;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync UCHAR Buf[32]; /* should be enough */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync } Buf;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ULONG cbBuf;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync UNICODE_STRING RtlStr;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync RtlInitUnicodeString(&RtlStr, pName);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync NTSTATUS Status = ZwQueryValueKey(hKey,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync &RtlStr,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeyValuePartialInformation,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync &Buf.Info,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync sizeof(Buf),
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync &cbBuf);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync if (Status == STATUS_SUCCESS)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync if (Buf.Info.Type == REG_DWORD)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync Assert(Buf.Info.DataLength == 4);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync *pDword = *((PULONG)Buf.Info.Data);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return STATUS_SUCCESS;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync }
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync }
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return STATUS_INVALID_PARAMETER;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT ULONG val)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync UNICODE_STRING RtlStr;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync RtlInitUnicodeString(&RtlStr, pName);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return ZwSetValueKey(hKey, &RtlStr,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync NULL, /* IN ULONG TitleIndex OPTIONAL, reserved */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync REG_DWORD,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync &val,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync sizeof(val));
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic NTSTATUS vboxDrvToolIoCompletionSetEvent(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp, IN PVOID pvContext)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync PKEVENT pEvent = (PKEVENT)pvContext;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeSetEvent(pEvent, 0, FALSE);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return STATUS_MORE_PROCESSING_REQUIRED;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostAsync(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync IoSetCompletionRoutine(pIrp, vboxDrvToolIoCompletionSetEvent, pEvent, TRUE, TRUE, TRUE);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return IoCallDriver(pDevObj, pIrp);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostSync(PDEVICE_OBJECT pDevObj, PIRP pIrp)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KEVENT Event;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeInitializeEvent(&Event, NotificationEvent, FALSE);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync NTSTATUS Status = VBoxDrvToolIoPostAsync(pDevObj, pIrp, &Event);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync if (Status == STATUS_PENDING)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync Status = pIrp->IoStatus.Status;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync }
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return Status;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync/* !!!NOTE: the caller MUST be the IRP owner!!! *
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync * !! one can not post threaded IRPs this way!! */
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsyncVBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostSyncWithTimeout(PDEVICE_OBJECT pDevObj, PIRP pIrp, ULONG dwTimeoutMs)
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync{
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync KEVENT Event;
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync LOG(("post irp (0x%p) to DevObj(0x%p) with timeout (%u)", pIrp, pDevObj, dwTimeoutMs));
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync KeInitializeEvent(&Event, NotificationEvent, FALSE);
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync NTSTATUS Status = VBoxDrvToolIoPostAsync(pDevObj, pIrp, &Event);
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync if (Status == STATUS_PENDING)
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync {
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync LARGE_INTEGER Interval;
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync PLARGE_INTEGER pInterval = NULL;
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync if (dwTimeoutMs != RT_INDEFINITE_WAIT)
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync {
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync Interval.QuadPart = -(int64_t) dwTimeoutMs /* ms */ * 10000;
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync pInterval = &Interval;
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync }
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, pInterval);
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync if (Status == STATUS_TIMEOUT)
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync {
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync WARN(("irp (0x%p) to DevObj(0x%p) was not completed within timeout (%u), cancelling", pIrp, pDevObj, dwTimeoutMs));
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync if (!IoCancelIrp(pIrp))
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync {
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync /* this may happen, but this is something the caller with timeout is not expecting */
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync WARN(("IoCancelIrp failed"));
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync }
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync /* wait for the IRP to complete */
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync }
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync else
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync {
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync ASSERT_WARN(Status == STATUS_SUCCESS, ("uunexpected Status (0x%x)", Status));
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync }
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync /* by this time the IRP is completed */
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync Status = pIrp->IoStatus.Status;
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync LOG(("Pending IRP(0x%p) completed with status(0x%x)", pIrp, Status));
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync }
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync else
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync {
85da04c2a4ab34e76410f9c1d83e2fa49800818cvboxsync LOG(("IRP(0x%p) completed with status(0x%x)", pIrp, Status));
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync }
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync return Status;
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync}
e04781b223e38e3b0c386d7e7c1dd7f30e9f6e90vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(VOID) VBoxDrvToolRefWaitEqual(PVBOXDRVTOOL_REF pRef, uint32_t u32Val)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync LARGE_INTEGER Interval;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync uint32_t cRefs;
9524aca332540e09e296d9ee84817c64fab1d560vboxsync size_t loops = 0;
9524aca332540e09e296d9ee84817c64fab1d560vboxsync KTIMER kTimer;
9524aca332540e09e296d9ee84817c64fab1d560vboxsync NTSTATUS status = STATUS_SUCCESS;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
9524aca332540e09e296d9ee84817c64fab1d560vboxsync KeInitializeTimer(&kTimer);
9524aca332540e09e296d9ee84817c64fab1d560vboxsync
9524aca332540e09e296d9ee84817c64fab1d560vboxsync while ((cRefs = ASMAtomicReadU32(&pRef->cRefs)) > u32Val && loops < 256)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync Assert(cRefs >= u32Val);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync Assert(cRefs < UINT32_MAX/2);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
9524aca332540e09e296d9ee84817c64fab1d560vboxsync KeSetTimer(&kTimer, Interval, NULL);
9524aca332540e09e296d9ee84817c64fab1d560vboxsync status = KeWaitForSingleObject(&kTimer, Executive, KernelMode, false, NULL);
9524aca332540e09e296d9ee84817c64fab1d560vboxsync Assert(NT_SUCCESS(status));
9524aca332540e09e296d9ee84817c64fab1d560vboxsync loops++;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync }
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolStrCopy(PUNICODE_STRING pDst, CONST PUNICODE_STRING pSrc)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync USHORT cbLength = pSrc->Length + sizeof (pDst->Buffer[0]);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync pDst->Buffer = (PWCHAR)vboxDrvToolMemAlloc(cbLength);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync Assert(pDst->Buffer);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync if (pDst->Buffer)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync RtlMoveMemory(pDst->Buffer, pSrc->Buffer, pSrc->Length);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync pDst->Buffer[pSrc->Length / sizeof (pDst->Buffer[0])] = L'\0';
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync pDst->Length = pSrc->Length;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync pDst->MaximumLength = cbLength;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return STATUS_SUCCESS;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync }
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return STATUS_NO_MEMORY;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncVBOXDRVTOOL_DECL(VOID) VBoxDrvToolStrFree(PUNICODE_STRING pStr)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync vboxDrvToolMemFree(pStr->Buffer);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}