VOID VIOSerialPortPnpNotifyWork( IN WDFWORKITEM WorkItem ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WorkItem); PVIOSERIAL_PORT pport = pdoData->port; PTARGET_DEVICE_CUSTOM_NOTIFICATION notification; ULONG requiredSize; NTSTATUS status; VIRTIO_PORT_STATUS_CHANGE portStatus = {0}; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__); portStatus.Version = 1; portStatus.Reason = pport->HostConnected; status = RtlULongAdd((sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION) - sizeof(UCHAR)), sizeof(VIRTIO_PORT_STATUS_CHANGE), &requiredSize); if (NT_SUCCESS(status)) { notification = (PTARGET_DEVICE_CUSTOM_NOTIFICATION) ExAllocatePoolWithTag(NonPagedPool, requiredSize, VIOSERIAL_DRIVER_MEMORY_TAG); if (notification != NULL) { RtlZeroMemory(notification, requiredSize); notification->Version = 1; notification->Size = (USHORT)(requiredSize); notification->FileObject = NULL; notification->NameBufferOffset = -1; notification->Event = GUID_VIOSERIAL_PORT_CHANGE_STATUS; RtlCopyMemory(notification->CustomDataBuffer, &portStatus, sizeof(VIRTIO_PORT_STATUS_CHANGE)); if(WdfDeviceGetDevicePnpState(pport->Device) == WdfDevStatePnpStarted) { status = IoReportTargetDeviceChangeAsynchronous( WdfDeviceWdmGetPhysicalDevice(pport->Device), notification, NULL, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "IoReportTargetDeviceChangeAsynchronous Failed! status = 0x%x\n", status); } } ExFreePoolWithTag(notification, VIOSERIAL_DRIVER_MEMORY_TAG); } } WdfObjectDelete(WorkItem); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__); }
STATIC PAGEABLE VOID messagetable_CountingCallback( _In_ PCMESSAGE_TABLE_ENTRY ptEntry, _In_opt_ PCMESSAGE_TABLE_ENTRY ptPreviousEntry, _In_ PVOID pvContext, _Out_ PBOOLEAN pbContinueEnumeration ) { NTSTATUS eStatus = STATUS_UNSUCCESSFUL; PCOUNTING_CALLBACK_CONTEXT ptContext = (PCOUNTING_CALLBACK_CONTEXT)pvContext; PAGED_CODE(); #ifndef DBG UNREFERENCED_PARAMETER(pbContinueEnumeration); #endif // !DBG ASSERT(NULL != ptEntry); ASSERT(NULL != pvContext); ASSERT(NULL != pbContinueEnumeration); ASSERT(*pbContinueEnumeration); if ((NULL == ptPreviousEntry) || (1 != ptEntry->nEntryId - ptPreviousEntry->nEntryId)) { // This is either the first time we entered the callback, // or the current ID begins a new block. eStatus = RtlULongAdd(ptContext->nBlocks, 1, &(ptContext->nBlocks)); ASSERT(NT_SUCCESS(eStatus)); } // Add the size for the current string. eStatus = RtlSIZETAdd(ptContext->cbTotalStrings, messagetable_SizeofSerializedEntry(ptEntry), &(ptContext->cbTotalStrings)); ASSERT(NT_SUCCESS(eStatus)); }
NTSTATUS BthEchoCliRetrieveServerSdpRecord( __in PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx, __out PBTH_SDP_STREAM_RESPONSE * ServerSdpRecord ) /*++ Description: Retrive server SDP record. We call this function on every file open to get the PSM Arguments: DevCtx - Client context ServerSdpRecord - SDP record retrieved Return Value: NTSTATUS Status code. --*/ { NTSTATUS status, statusReuse, disconnectStatus; WDF_MEMORY_DESCRIPTOR inMemDesc; WDF_MEMORY_DESCRIPTOR outMemDesc; WDF_REQUEST_REUSE_PARAMS ReuseParams; BTH_SDP_CONNECT connect = {0}; BTH_SDP_DISCONNECT disconnect = {0}; BTH_SDP_SERVICE_ATTRIBUTE_SEARCH_REQUEST requestSdp = {0}; BTH_SDP_STREAM_RESPONSE responseSdp = {0}; ULONG requestSize; PBTH_SDP_STREAM_RESPONSE serverSdpRecord = NULL; WDFREQUEST request; WDF_OBJECT_ATTRIBUTES attributes; PAGED_CODE(); // // Allocate the request we will use for obtaining sdp record // NOTE that we do it for every file open, hence we // // can't use reserve request from the context // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); status = WdfRequestCreate( &attributes, DevCtx->Header.IoTarget, &request ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Failed to allocate request for retriving server sdp record, Status code %!STATUS!\n", status); goto exit; } connect.bthAddress = DevCtx->ServerBthAddress; connect.requestTimeout = SDP_REQUEST_TO_DEFAULT; connect.fSdpConnect = 0; // // Connect to the SDP service. // WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &connect, sizeof(connect) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, &connect, sizeof(connect) ); status = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_CONNECT, &inMemDesc, &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "IOCTL_BTH_SDP_CONNECT failed, Status code %!STATUS!\n", status); goto exit1; } // // Obtain the required size of the SDP record // requestSdp.hConnection = connect.hConnection; requestSdp.uuids[0].u.uuid128 = BTHECHOSAMPLE_SVC_GUID; requestSdp.uuids[0].uuidType = SDP_ST_UUID128; requestSdp.range[0].minAttribute = 0; requestSdp.range[0].maxAttribute = 0xFFFF; WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(request, &ReuseParams); ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &requestSdp, sizeof(requestSdp) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, &responseSdp, sizeof(responseSdp) ); status = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH, &inMemDesc, &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH failed while querying response size, " "status code %!STATUS!\n", status); goto exit2; } // // Allocate the required size for SDP record // status = RtlULongAdd( responseSdp.requiredSize, sizeof(BTH_SDP_STREAM_RESPONSE), &requestSize ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "SDP record size too large, status code %!STATUS!\n", status); goto exit2; } serverSdpRecord = ExAllocatePoolWithTag(NonPagedPool, requestSize, POOLTAG_BTHECHOSAMPLE); if (NULL == serverSdpRecord) { status = STATUS_INSUFFICIENT_RESOURCES; TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "Allocating SDP record failed, returning status code %!STATUS!\n", status); goto exit2; } // // Send request with required size // WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(request, &ReuseParams); ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &requestSdp, sizeof(requestSdp) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, serverSdpRecord, requestSize ); status = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH, &inMemDesc, &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH failed, status code %!STATUS!\n", status); ExFreePoolWithTag(serverSdpRecord, POOLTAG_BTHECHOSAMPLE); } else { *ServerSdpRecord = serverSdpRecord; } exit2: // // Disconnect from SDP service. // WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(request, &ReuseParams); ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); disconnect.hConnection = connect.hConnection; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &disconnect, sizeof(disconnect) ); disconnectStatus = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_DISCONNECT, &inMemDesc, NULL, //outMemDesc NULL, //sendOptions NULL //bytesReturned ); ASSERT(NT_SUCCESS(disconnectStatus)); //Disconnect should not fail if (!NT_SUCCESS(disconnectStatus)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "IOCTL_BTH_SDP_DISCONNECT failed, Status code %!STATUS!\n", status); } exit1: WdfObjectDelete(request); exit: return status; }
NTSTATUS DsppLoadFontFile ( _In_ PWCHAR FontFileName ) { PBL_DEVICE_DESCRIPTOR FontDevice; NTSTATUS Status; ULONG NameLength, DirectoryLength, TotalLength; PWCHAR FontPath, FontDirectory; BL_LIBRARY_PARAMETERS LibraryParameters; BOOLEAN CustomDirectory, CustomDevice; /* Initialize locals */ CustomDirectory = TRUE; CustomDevice = TRUE; FontDevice = NULL; FontPath = NULL; FontDirectory = NULL; /* Check if a custom font path should be used */ Status = BlGetBootOptionString(BlpApplicationEntry.BcdData, BcdLibraryString_FontPath, &FontDirectory); if (!NT_SUCCESS(Status)) { /* Nope, use the one configured by the library */ CustomDirectory = FALSE; RtlCopyMemory(&LibraryParameters, &BlpLibraryParameters, sizeof(LibraryParameters)), FontDirectory = LibraryParameters.FontBaseDirectory; } /* Do we still not have a font directory? */ if (!FontDirectory) { /* Use the boot device and boot directory */ FontDevice = BlpBootDevice; FontDirectory = L"\\EFI\\Microsoft\\Boot\\Fonts"; CustomDevice = FALSE; } else { /* Otherwise, if we have a font directory, what device is the app on? */ Status = BlGetBootOptionDevice(BlpApplicationEntry.BcdData, BcdLibraryDevice_ApplicationDevice, &FontDevice, NULL); if (!NT_SUCCESS(Status)) { /* If we don't know the device, we can't open the path */ goto Quickie; } } /* Figure out the length of the file name, and of the directory */ NameLength = wcslen(FontFileName); DirectoryLength = wcslen(FontDirectory); /* Safely add them up*/ Status = RtlULongAdd(NameLength, DirectoryLength, &TotalLength); if (!NT_SUCCESS(Status)) { goto Quickie; } /* Convert to bytes */ Status = RtlULongLongToULong(TotalLength * sizeof(WCHAR), &TotalLength); if (!NT_SUCCESS(Status)) { goto Quickie; } /* Add a terminating NUL */ Status = RtlULongAdd(TotalLength, sizeof(UNICODE_NULL), &TotalLength); if (!NT_SUCCESS(Status)) { goto Quickie; } /* Allocate the final buffer for it */ FontPath = BlMmAllocateHeap(TotalLength); if (!FontPath) { Status = STATUS_NO_MEMORY; goto Quickie; } /* Concatenate the directory with the file name */ wcscpy(FontPath, FontDirectory); wcscat(FontPath, FontFileName); /* Try to load this font */ Status = BfLoadFontFile(FontDevice, FontPath); Quickie: /* Check if we had a custom font device allocated and free it */ if ((CustomDevice) && (FontDevice)) { BlMmFreeHeap(FontDevice); } /* Check if we had a custom font directory allocated and free it */ if ((FontDirectory) && (CustomDirectory)) { BlMmFreeHeap(FontDirectory); } /* Check if we had allocated a font path and free it */ if (FontPath) { BlMmFreeHeap(FontPath); } /* Return back */ return Status; }
NTSTATUS BlGetBootOptionString ( _In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PWCHAR* Value ) { NTSTATUS Status; PBL_BCD_OPTION Option; PWCHAR String, StringCopy; ULONG StringLength; BcdElementType ElementType; //PGUID AppIdentifier; /* Make sure this is a BCD_STRING */ ElementType.PackedValue = Type; if (ElementType.Format != BCD_TYPE_STRING) { return STATUS_INVALID_PARAMETER; } /* Return the data */ Option = MiscGetBootOption(List, Type); if (Option) { /* Extract the string */ String = (PWCHAR)((ULONG_PTR)Option + Option->DataOffset); Status = STATUS_SUCCESS; } else { /* No string is present */ String = NULL; Status = STATUS_NOT_FOUND; } /* Compute the data size */ StringLength = Option->DataSize / sizeof(WCHAR); #ifdef _SECURE_BOOT_ /* Filter out SecureBoot Options */ AppIdentifier = BlGetApplicationIdentifier(); Status = BlpBootOptionCallbackString(AppIdentifier, Type, String, StringLength, &String, &StringLength); #else #endif /* Make sure we have a valid, non-filtered string */ if (NT_SUCCESS(Status)) { /* Check if we have space for one more character */ Status = RtlULongAdd(StringLength, 1, &StringLength); if (NT_SUCCESS(Status)) { /* Check if it's safe to multiply by two */ Status = RtlULongMult(StringLength, sizeof(WCHAR), &StringLength); if (NT_SUCCESS(Status)) { /* Allocate a copy for the string */ StringCopy = BlMmAllocateHeap(StringLength); if (StringCopy) { /* NULL-terminate it */ RtlCopyMemory(StringCopy, String, StringLength - sizeof(UNICODE_NULL)); StringCopy[StringLength] = UNICODE_NULL; *Value = StringCopy; Status = STATUS_SUCCESS; } else { /* No memory, fail */ Status = STATUS_NO_MEMORY; } } } } /* All done */ return Status; }
PDRIVE_LAYOUT_INFORMATION DiskConvertExtendedToLayout( IN CONST PDRIVE_LAYOUT_INFORMATION_EX LayoutEx ) { ULONG i; ULONG LayoutSize; PDRIVE_LAYOUT_INFORMATION Layout; PPARTITION_INFORMATION Partition; PPARTITION_INFORMATION_EX PartitionEx; NTSTATUS status; PAGED_CODE (); ASSERT ( LayoutEx ); // // The only valid conversion is from an MBR extended layout structure to // the old structure. // if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR) { ASSERT ( FALSE ); return NULL; } // // Use safe interger function // status = RtlULongMult(LayoutEx->PartitionCount, sizeof(PARTITION_INFORMATION), &LayoutSize); if (!NT_SUCCESS(status)) { return NULL; } status = RtlULongAdd(LayoutSize, FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]), &LayoutSize); if (!NT_SUCCESS(status)) { return NULL; } Layout = ExAllocatePoolWithTag ( NonPagedPool, LayoutSize, DISK_TAG_PART_LIST ); if ( Layout == NULL ) { return NULL; } Layout->Signature = LayoutEx->Mbr.Signature; Layout->PartitionCount = LayoutEx->PartitionCount; for (i = 0; i < LayoutEx->PartitionCount; i++) { Partition = &Layout->PartitionEntry[i]; PartitionEx = &LayoutEx->PartitionEntry[i]; Partition->StartingOffset = PartitionEx->StartingOffset; Partition->PartitionLength = PartitionEx->PartitionLength; Partition->RewritePartition = PartitionEx->RewritePartition; Partition->PartitionNumber = PartitionEx->PartitionNumber; Partition->PartitionType = PartitionEx->Mbr.PartitionType; Partition->BootIndicator = PartitionEx->Mbr.BootIndicator; Partition->RecognizedPartition = PartitionEx->Mbr.RecognizedPartition; Partition->HiddenSectors = PartitionEx->Mbr.HiddenSectors; } return Layout; }
PDRIVE_LAYOUT_INFORMATION_EX DiskConvertLayoutToExtended( IN CONST PDRIVE_LAYOUT_INFORMATION Layout ) /*++ Routine Description: Convert a DRIVE_LAYOUT_INFORMATION structure into a DRIVE_LAYOUT_INFORMATION_EX structure. Arguments: Layout - The source DRIVE_LAYOUT_INFORMATION structure. Return Values: The resultant DRIVE_LAYOUT_INFORMATION_EX structure. This buffer must be freed by the callee using ExFreePool. --*/ { ULONG i; ULONG size; PDRIVE_LAYOUT_INFORMATION_EX layoutEx; NTSTATUS status; PAGED_CODE (); ASSERT ( Layout != NULL ); // // Allocate enough space for a DRIVE_LAYOUT_INFORMATION_EX structure // plus as many PARTITION_INFORMATION_EX structures as are in the // source array. // // // Use safe interger function // status = RtlULongMult(Layout->PartitionCount, sizeof(PARTITION_INFORMATION_EX), &size); if (!NT_SUCCESS(status)) { return NULL; } status = RtlULongAdd(size, FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]), &size); if (!NT_SUCCESS(status)) { return NULL; } layoutEx = ExAllocatePoolWithTag( NonPagedPool, size, DISK_TAG_PART_LIST ); if ( layoutEx == NULL ) { return NULL; } // // Convert the disk information. // layoutEx->PartitionStyle = PARTITION_STYLE_MBR; layoutEx->PartitionCount = Layout->PartitionCount; layoutEx->Mbr.Signature = Layout->Signature; for (i = 0; i < Layout->PartitionCount; i++) { // // Convert each entry. // DiskConvertPartitionToExtended ( &Layout->PartitionEntry[i], &layoutEx->PartitionEntry[i] ); } return layoutEx; }
PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo) { PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension; PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData; PTRANSFER_PACKET newPkt = NULL; ULONG transferLength; NTSTATUS status = STATUS_SUCCESS; if (NT_SUCCESS(status)) { status = RtlULongAdd(fdoData->HwMaxXferLen, PAGE_SIZE, &transferLength); if (!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "Integer overflow in calculating transfer packet size.")); status = STATUS_INTEGER_OVERFLOW; } } /* * Allocate the actual packet. */ if (NT_SUCCESS(status)) { newPkt = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSFER_PACKET), 'pnPC'); if (newPkt == NULL) { TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate transfer packet.")); status = STATUS_INSUFFICIENT_RESOURCES; } else { RtlZeroMemory(newPkt, sizeof(TRANSFER_PACKET)); } } /* * Allocate Irp for the packet. */ if (NT_SUCCESS(status)) { newPkt->Irp = IoAllocateIrp(Fdo->StackSize, FALSE); if (newPkt->Irp == NULL) { TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate IRP for transfer packet.")); status = STATUS_INSUFFICIENT_RESOURCES; } } /* * Allocate a MDL. Add one page to the length to insure an extra page * entry is allocated if the buffer does not start on page boundaries. */ if (NT_SUCCESS(status)) { newPkt->PartialMdl = IoAllocateMdl(NULL, transferLength, FALSE, FALSE, NULL); if (newPkt->PartialMdl == NULL) { TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate MDL for transfer packet.")); status = STATUS_INSUFFICIENT_RESOURCES; } else { ASSERT(newPkt->PartialMdl->Size >= (CSHORT)(sizeof(MDL) + BYTES_TO_PAGES(fdoData->HwMaxXferLen) * sizeof(PFN_NUMBER))); } } /* * Allocate per-packet retry history, if required */ if (NT_SUCCESS(status) && (fdoData->InterpretSenseInfo != NULL) ) { // attempt to allocate also the history ULONG historyByteCount = 0; // SAL annotation and ClassInitializeEx() should both catch this case ASSERT(fdoData->InterpretSenseInfo->HistoryCount != 0); __analysis_assume(fdoData->InterpretSenseInfo->HistoryCount != 0); historyByteCount = sizeof(SRB_HISTORY_ITEM) * fdoData->InterpretSenseInfo->HistoryCount; historyByteCount += sizeof(SRB_HISTORY) - sizeof(SRB_HISTORY_ITEM); newPkt->RetryHistory = (PSRB_HISTORY)ExAllocatePoolWithTag(NonPagedPool, historyByteCount, 'hrPC'); if (newPkt->RetryHistory == NULL) { TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate MDL for transfer packet.")); status = STATUS_INSUFFICIENT_RESOURCES; } else { // call this routine directly once since it's the first initialization of // the structure and the internal maximum count field is not yet setup. HistoryInitializeRetryLogs(newPkt->RetryHistory, fdoData->InterpretSenseInfo->HistoryCount); } } /* * Enqueue the packet in our static AllTransferPacketsList * (just so we can find it during debugging if its stuck somewhere). */ if (NT_SUCCESS(status)) { KIRQL oldIrql; newPkt->Fdo = Fdo; #if DBG newPkt->DbgPktId = InterlockedIncrement(&fdoData->DbgMaxPktId); #endif KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql); InsertTailList(&fdoData->AllTransferPacketsList, &newPkt->AllPktsListEntry); KeReleaseSpinLock(&fdoData->SpinLock, oldIrql); } else { // free any resources acquired above (in reverse order) if (newPkt != NULL) { FREE_POOL(newPkt->RetryHistory); if (newPkt->PartialMdl != NULL) { IoFreeMdl(newPkt->PartialMdl); } if (newPkt->Irp != NULL) { IoFreeIrp(newPkt->Irp); } FREE_POOL(newPkt); } } return newPkt; }
NTSTATUS BiEnumerateElements ( _In_ HANDLE BcdHandle, _In_ HANDLE ObjectHandle, _In_ ULONG RootElementType, _In_ ULONG Flags, _Out_opt_ PBCD_PACKED_ELEMENT Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount ) { HANDLE ElementsHandle, ElementHandle; ULONG TotalLength, RegistryElementDataLength, RemainingLength; NTSTATUS Status; ULONG i; PVOID ElementData, SubObjectList, RegistryElementData; BcdElementType ElementType; PBCD_PACKED_ELEMENT PreviousElement, ElementsStart; ULONG SubElementCount, SubKeyCount, SubObjectCount, ElementDataLength; PWCHAR ElementName; PWCHAR* SubKeys; /* Assume failure */ *ElementCount = 0; /* Initialize all locals that are checked at the end*/ SubKeys = NULL; ElementsHandle = NULL; ElementHandle = NULL; ElementData = NULL; RegistryElementData = NULL; PreviousElement = NULL; ElementName = NULL; SubObjectList = NULL; TotalLength = 0; ElementDataLength = 0; SubObjectCount = 0; RemainingLength = 0; ElementsStart = Elements; /* Open the root object key's elements */ Status = BiOpenKey(ObjectHandle, L"Elements", &ElementsHandle); if (!NT_SUCCESS(Status)) { goto Quickie; } /* Enumerate all elements */ Status = BiEnumerateSubKeys(ElementsHandle, &SubKeys, &SubKeyCount); if (!NT_SUCCESS(Status)) { goto Quickie; } /* Iterate over each one */ for (i = 0; i < SubKeyCount; i++) { /* Open the element */ ElementName = SubKeys[i]; Status = BiOpenKey(ElementsHandle, ElementName, &ElementHandle); if (!NT_SUCCESS(Status)) { EfiPrintf(L"ELEMENT ERROR: %lx\r\n", Status); EfiStall(100000); break; } /* The name of the element is its data type */ ElementType.PackedValue = wcstoul(SubKeys[i], NULL, 16); if (!(ElementType.PackedValue) || (ElementType.PackedValue == -1)) { EfiPrintf(L"Value invalid\r\n"); BiCloseKey(ElementHandle); ElementHandle = 0; continue; } /* Read the appropriate registry value type for this element */ Status = BiGetRegistryValue(ElementHandle, L"Element", BiConvertElementFormatToValueType( ElementType.Format), &RegistryElementData, &RegistryElementDataLength); if (!NT_SUCCESS(Status)) { EfiPrintf(L"Element invalid\r\n"); break; } /* Now figure out how much space the converted element will need */ ElementDataLength = 0; Status = BiConvertRegistryDataToElement(ObjectHandle, RegistryElementData, RegistryElementDataLength, ElementType, NULL, &ElementDataLength); if (Status != STATUS_BUFFER_TOO_SMALL) { break; } /* Allocate a buffer big enough for the converted element */ ElementData = BlMmAllocateHeap(ElementDataLength); if (!ElementData) { Status = STATUS_INSUFFICIENT_RESOURCES; break; } /* And actually convert it this time around */ Status = BiConvertRegistryDataToElement(ObjectHandle, RegistryElementData, RegistryElementDataLength, ElementType, ElementData, &ElementDataLength); if (!NT_SUCCESS(Status)) { break; } /* Safely add space for the packed element header */ Status = RtlULongAdd(TotalLength, FIELD_OFFSET(BCD_PACKED_ELEMENT, Data), &TotalLength); if (!NT_SUCCESS(Status)) { break; } /* Safely add space for the data of the element itself */ Status = RtlULongAdd(TotalLength, ElementDataLength, &TotalLength); if (!NT_SUCCESS(Status)) { break; } /* One more element */ ++*ElementCount; /* See how much space we were given */ RemainingLength = *ElementSize; if (RemainingLength >= TotalLength) { /* Set the next pointer */ Elements->NextEntry = (PBCD_PACKED_ELEMENT)((ULONG_PTR)ElementsStart + TotalLength); /* Fill this one out */ Elements->RootType.PackedValue = RootElementType; Elements->Version = 1; Elements->Type = ElementType.PackedValue; Elements->Size = ElementDataLength; /* Add the data */ RtlCopyMemory(Elements->Data, ElementData, ElementDataLength); RemainingLength -= TotalLength; /* Move to the next element on the next pass */ PreviousElement = Elements; Elements = Elements->NextEntry; } else { /* We're out of space */ RemainingLength = 0; } /* Are we enumerating devices, and is this a device? */ if ((Flags & BCD_ENUMERATE_FLAG_DEVICES) && (ElementType.Format == BCD_TYPE_DEVICE)) { /* Yep, so go inside to enumerate it */ Status = BiEnumerateSubElements(BcdHandle, ElementData, ElementType.PackedValue, Flags, &Elements, &ElementDataLength, &SubElementCount); if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL)) { /* Safely add the length of the sub elements */ Status = RtlULongAdd(TotalLength, ElementDataLength, &TotalLength); if (!NT_SUCCESS(Status)) { break; } /* Add the sub elements to the total */ *ElementCount += SubElementCount; /* See if we have enough space*/ if (*ElementSize >= TotalLength) { /* Were there any subelements? */ if (SubElementCount) { /* Update to keep track of these new subelements */ ElementDataLength = *ElementSize - TotalLength; /* Link the subelements into the chain */ PreviousElement = Elements; PreviousElement->NextEntry = (PBCD_PACKED_ELEMENT)((ULONG_PTR)ElementsStart + TotalLength); Elements = PreviousElement->NextEntry; } } else { /* We're out of space */ ElementDataLength = 0; } } else if ((Status != STATUS_NOT_FOUND) && (Status != STATUS_OBJECT_NAME_NOT_FOUND)) { /* Fatal error trying to read the data, so fail */ break; } } else if ((Flags & BCD_ENUMERATE_FLAG_DEEP) && (ElementType.PackedValue == BcdLibraryObjectList_InheritedObjects)) { /* Inherited objects are requsted, so allocate a buffer for them */ SubObjectList = BlMmAllocateHeap(ElementDataLength); if (!SubObjectList) { Status = STATUS_INSUFFICIENT_RESOURCES; break; } /* Copy the elements into the list. They are arrays of GUIDs */ RtlCopyMemory(SubObjectList, ElementData, ElementDataLength); SubObjectCount = ElementDataLength / sizeof(GUID); } /* Free our local buffers */ BlMmFreeHeap(ElementData); BlMmFreeHeap(RegistryElementData); ElementData = NULL; RegistryElementData = NULL; /* Close the key */ BiCloseKey(ElementHandle); ElementHandle = NULL; ElementName = NULL; } /* Did we end up here with a sub object list after successful loop parsing? */ if ((i != 0) && (i == SubKeyCount) && (SubObjectList)) { /* We will actually enumerate it now, at the end */ Status = BiEnumerateSubObjectElements(BcdHandle, SubObjectList, SubObjectCount, Flags, Elements, &RemainingLength, &SubElementCount); if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL)) { /* Safely add the length of the sub elements */ Status = RtlULongAdd(TotalLength, RemainingLength, &TotalLength); if ((NT_SUCCESS(Status)) && (SubElementCount)) { /* Add the sub elements to the total */ *ElementCount += SubElementCount; /* Don't touch PreviousElement anymore */ PreviousElement = NULL; } } } Quickie: /* Free the sub object list, if any */ if (SubObjectList) { BlMmFreeHeap(SubObjectList); } /* Free any local element data */ if (ElementData) { BlMmFreeHeap(ElementData); } /* Free any local registry data */ if (RegistryElementData) { BlMmFreeHeap(RegistryElementData); } /* Close the handle if still opened */ if (ElementHandle) { BiCloseKey(ElementHandle); } /* Terminate the last element, if any */ if (PreviousElement) { PreviousElement->NextEntry = NULL; } /* Close the root handle if still opened */ if (ElementsHandle) { BiCloseKey(ElementsHandle); } /* Set failure code if out of space */ if (*ElementSize < TotalLength) { Status = STATUS_BUFFER_TOO_SMALL; } /* Other errors will send a notification error */ if (!(NT_SUCCESS(Status)) && (Status != STATUS_BUFFER_TOO_SMALL)) { BiNotifyEnumerationError(ObjectHandle, ElementName, Status); } /* Finally free the subkeys array */ if (SubKeys) { BlMmFreeHeap(SubKeys); } /* And return the required, final length and status */ *ElementSize = TotalLength; return Status; }
NTSTATUS BiEnumerateSubObjectElements ( _In_ HANDLE BcdHandle, _Out_ PGUID SubObjectList, _In_ ULONG SubObjectCount, _In_ ULONG Flags, _Out_opt_ PBCD_PACKED_ELEMENT Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount ) { NTSTATUS Status; ULONG SubElementCount, TotalSize, RequiredSize, CurrentSize, i; PBCD_PACKED_ELEMENT PreviousElement; /* Assume empty list */ *ElementCount = 0; Status = STATUS_SUCCESS; /* Initialize variables */ TotalSize = 0; PreviousElement = NULL; /* Set the currently remaining size based on caller's input */ CurrentSize = *ElementSize; /* Iterate over every subje object */ for (i = 0; i < SubObjectCount; i++) { /* Set the currently remaining buffer space */ RequiredSize = CurrentSize; /* Enumerate the inherited sub elements */ Status = BiEnumerateSubElements(BcdHandle, &SubObjectList[i], BcdLibraryObjectList_InheritedObjects, Flags, &Elements, &RequiredSize, &SubElementCount); if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL)) { /* Safely add the length of the sub elements */ Status = RtlULongAdd(TotalSize, RequiredSize, &TotalSize); if (!NT_SUCCESS(Status)) { break; } /* Add the sub elements to the total */ *ElementCount += SubElementCount; /* See if we have enough space*/ if (*ElementSize >= TotalSize) { /* Were there any subelements? */ if (SubElementCount) { /* Update to keep track of these new subelements */ CurrentSize = *ElementSize - TotalSize; /* Link the subelements into the chain */ PreviousElement = Elements; PreviousElement->NextEntry = (PBCD_PACKED_ELEMENT)((ULONG_PTR)Elements + TotalSize); Elements = PreviousElement->NextEntry; } } else { /* We're out of space */ CurrentSize = 0; } } else if ((Status != STATUS_NOT_FOUND) && (Status != STATUS_OBJECT_NAME_NOT_FOUND)) { /* Some other fatal error, break out */ break; } else { /* The sub element was not found, print a warning but keep going */ BlStatusPrint(L"Ignoring missing BCD inherit object: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", (&SubObjectList[i])->Data1, (&SubObjectList[i])->Data2, (&SubObjectList[i])->Data3, (&SubObjectList[i])->Data4[0], (&SubObjectList[i])->Data4[1], (&SubObjectList[i])->Data4[2], (&SubObjectList[i])->Data4[3], (&SubObjectList[i])->Data4[4], (&SubObjectList[i])->Data4[5], (&SubObjectList[i])->Data4[6], (&SubObjectList[i])->Data4[7], (&SubObjectList[i])->Data4[8]); Status = STATUS_SUCCESS; } } /* Terminate the last element, if one was left */ if (PreviousElement) { PreviousElement->NextEntry = NULL; } /* Set failure code if we ran out of space */ if (*ElementSize < TotalSize) { Status = STATUS_BUFFER_TOO_SMALL; } /* Return final length and status */ *ElementSize = TotalSize; return Status; }
NTSTATUS BiConvertBcdElements ( _In_ PBCD_PACKED_ELEMENT Elements, _Out_opt_ PBCD_ELEMENT Buffer, _Inout_ PULONG BufferSize, _Inout_ PULONG ElementCount ) { NTSTATUS Status; ULONG ElementSize, AlignedElementSize, AlignedDataSize; PBCD_ELEMENT_HEADER Header; PVOID Data; BOOLEAN Exists; ULONG i, j, Count; /* Local variable to keep track of objects */ Count = 0; /* Safely compute the element bytes needed */ Status = RtlULongMult(*ElementCount, sizeof(BCD_ELEMENT), &ElementSize); if (!NT_SUCCESS(Status)) { return Status; } /* Safely align the element size */ Status = RtlULongAdd(ElementSize, sizeof(ULONG) - 1, &AlignedElementSize); if (!NT_SUCCESS(Status)) { return Status; } AlignedElementSize = ALIGN_DOWN(AlignedElementSize, ULONG); /* Do a safe version of Add2Ptr to figure out where the headers will start */ Status = RtlULongPtrAdd((ULONG_PTR)Buffer, AlignedElementSize, (PULONG_PTR)&Header); if (!NT_SUCCESS(Status)) { return Status; } /* Safely compute the header bytes needed */ Status = RtlULongMult(*ElementCount, sizeof(BCD_ELEMENT_HEADER), &ElementSize); if (!NT_SUCCESS(Status)) { return Status; } /* Safely align the header size */ Status = RtlULongAdd(ElementSize, AlignedElementSize + sizeof(ULONG) - 1, &AlignedElementSize); if (!NT_SUCCESS(Status)) { return Status; } AlignedElementSize = ALIGN_DOWN(AlignedElementSize, ULONG); /* Do a safe version of Add2Ptr */ Status = RtlULongPtrAdd((ULONG_PTR)Buffer, AlignedElementSize, (PULONG_PTR)&Data); if (!NT_SUCCESS(Status)) { return Status; } /* Iterate over every element */ for (i = 0; i < *ElementCount; i++) { /* Safely align the element size */ Status = RtlULongAdd(Elements->Size, sizeof(ULONG) - 1, &AlignedDataSize); if (!NT_SUCCESS(Status)) { break; } AlignedDataSize = ALIGN_DOWN(AlignedDataSize, ULONG); /* Safely add the size of this data element */ Status = RtlULongAdd(AlignedElementSize, AlignedDataSize, &AlignedElementSize); if (!NT_SUCCESS(Status)) { break; } /* Do we have enough space left? */ if (*BufferSize >= AlignedElementSize) { /* Check if our root is an inherited object */ Exists = FALSE; if (Elements->RootType.PackedValue == BcdLibraryObjectList_InheritedObjects) { /* Yes, scan for us in the current buffer */ for (j = 0; j < Count; j++) { /* Do we already exist? */ while (Buffer[j].Header->Type == Elements->RootType.PackedValue) { /* Yep */ Exists = TRUE; break; } } } /* Have we already found ourselves? */ if (!Exists) { /* Nope, one more entry */ ++Count; /* Write out the unpacked object */ Buffer->Body = Data; Buffer->Header = Header; /* Fill out its header */ Header->Size = Elements->Size; Header->Type = Elements->Type; Header->Version = Elements->Version; /* And copy the data */ RtlCopyMemory(Data, Elements->Data, Header->Size); /* Move to the next unpacked object and header */ ++Buffer; ++Header; /* Move to the next data entry */ Data = (PVOID)((ULONG_PTR)Data + AlignedDataSize); } } else { /* Nope, set failure code, but keep going so we can return count */ Status = STATUS_BUFFER_TOO_SMALL; } /* Move to the next element entry */ Elements = Elements->NextEntry; } /* Return the new final buffer size and count */ *BufferSize = AlignedElementSize; *ElementCount = Count; return Status; }
NTSTATUS NICAddWakeUpPattern( IN PFDO_DATA FdoData, IN PVOID InformationBuffer, IN UINT InformationBufferLength, OUT PULONG BytesRead, OUT PULONG BytesNeeded ) /*++ Routine Description: This routine will allocate a local memory structure, copy the pattern, insert the pattern into a linked list and return success We are gauranteed that we wll get only one request at a time, so this is implemented without locks. Arguments: FdoData FdoData structure InformationBuffer Wake up Pattern InformationBufferLength Wake Up Pattern Length Return Value: STATUS_Success - if successful. STATUS_UNSUCCESSFUL - if memory allocation fails. --*/ { NTSTATUS status = STATUS_UNSUCCESSFUL; PMP_WAKE_PATTERN pWakeUpPattern = NULL; ULONG AllocationLength = 0; PNDIS_PM_PACKET_PATTERN pPmPattern = NULL; ULONG Signature = 0; ULONG CopyLength = 0; ULONG safeAddResult; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER, "--> NICAddWakeUpPattern\n"); do { if(!FdoData->AllowWakeArming) { status = STATUS_NOT_SUPPORTED; break; } pPmPattern = (PNDIS_PM_PACKET_PATTERN) InformationBuffer; if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN)) { status = STATUS_BUFFER_TOO_SMALL; *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN); break; } // // safeAddResult = pPmPattern->PatternOffset + pPmPattern->PatternSize // status = RtlULongAdd( pPmPattern->PatternOffset, pPmPattern->PatternSize, &safeAddResult) ; if (!NT_SUCCESS(status)) { break; } if (InformationBufferLength < safeAddResult) { status = STATUS_BUFFER_TOO_SMALL; *BytesNeeded = safeAddResult; break; } *BytesRead = safeAddResult; // // Calculate the e100 signature // status = MPCalculateE100PatternForFilter ( (PUCHAR)pPmPattern+ pPmPattern->PatternOffset, pPmPattern->PatternSize, (PUCHAR)pPmPattern +sizeof(NDIS_PM_PACKET_PATTERN), pPmPattern->MaskSize, &Signature ); if ( status != STATUS_SUCCESS) { break; } CopyLength = safeAddResult; // // Allocate the memory to hold the WakeUp Pattern // // AllocationLength = sizeof (MP_WAKE_PATTERN) + CopyLength; // status = RtlULongAdd( sizeof(MP_WAKE_PATTERN), CopyLength, &AllocationLength); if (!NT_SUCCESS(status)) { break; } pWakeUpPattern = ExAllocatePoolWithTag(NonPagedPool, AllocationLength, PCIDRV_POOL_TAG); if (!pWakeUpPattern) { break; } // // Initialize pWakeUpPattern // RtlZeroMemory (pWakeUpPattern, AllocationLength); pWakeUpPattern->AllocationSize = AllocationLength; pWakeUpPattern->Signature = Signature; // // Copy the pattern into local memory // RtlMoveMemory (&pWakeUpPattern->Pattern[0], InformationBuffer, CopyLength); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); // // Insert the pattern into the list // /* ExInterlockedInsertHeadList (&FdoData->PoMgmt.PatternList, &pWakeUpPattern->linkListEntry, &FdoData->Lock); */ WdfSpinLockAcquire(FdoData->Lock); InsertHeadList(&FdoData->PoMgmt.PatternList,&pWakeUpPattern->linkListEntry ); WdfSpinLockRelease(FdoData->Lock); status = STATUS_SUCCESS; } WHILE (FALSE); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER, "<-- NICAddWakeUpPattern\n"); return status; }