os_result_t efi_get_memory_map( efi_memory_descriptor_t** array, uintn_t* array_count, uintn_t* map_key, uintn_t* descriptor_size, uintn_t* descriptor_version ) { os_result_t status = S_OK; efi_memory_descriptor_t* buffer = NULL; uintn_t buffer_size = sizeof(efi_memory_descriptor_t); while (efi_memory_grow_pool(&status, (void**)&buffer, buffer_size) == S_OK) { efi_status_t efi_call_status = fw_efi_bt->get_memory_map(&buffer_size, buffer, map_key, descriptor_size, descriptor_version); status = efi_get_system_status(efi_call_status); } if (OS_SUCCESS(status)) { (*array) = buffer; (*array_count) = buffer_size / *descriptor_size; } return status; }
///------------------------------------------------------------------------------------------------- /// /// \brief Securely compares two memory blocks. /// /// \param[in] source1 Provides pointer to first memory block. /// \param[in] source2_length Provides number of bytes in first memory block. /// \param[in] source2 Provides pointer to second memory block. /// \param[in] source2_length Provides number of bytes in second memory block. /// \param[out] result Returns @c true when source1 and source2 content is equal; /// @c false otherwise /// /// \retval E_INVALID_ARGUMENT At least one invalid argument provided. /// \retval S_OK Operation successful. /// ///------------------------------------------------------------------------------------------------- OS_NOLIBCALL os_result_t rtl_memory_equals_s( const void* source1, size_t source1_length, const void* source2, size_t source2_length, bool* result ) { if (OS_EXPECT_FALSE(result == NULL)) { return E_INVALID_ARGUMENT; } size_t compared = 0; os_result_t status = rtl_memory_prefix_s(source1, source1_length, source2, source2_length, &compared); if (OS_SUCCESS(status)) { (*result) = (compared == source2_length); } return status; }
/************************************************************************* * * Function: UDFCommonShutdown() * * Description: * The actual work is performed here. Basically, all we do here is * internally invoke a flush on all mounted logical volumes. This, in * tuen, will result in all open file streams being flushed to disk. * * Expected Interrupt Level (for execution) : * * IRQL_PASSIVE_LEVEL * * Return Value: Irrelevant * *************************************************************************/ NTSTATUS UDFCommonShutdown( PtrUDFIrpContext PtrIrpContext, PIRP Irp ) { NTSTATUS RC = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp = NULL; PVCB Vcb; PLIST_ENTRY Link; PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL; LARGE_INTEGER delay; KdPrint(("UDFCommonShutdown\n")); _SEH2_TRY { // First, get a pointer to the current I/O stack location IrpSp = IoGetCurrentIrpStackLocation(Irp); ASSERT(IrpSp); Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN)); if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES); // (a) Block all new "mount volume" requests by acquiring an appropriate // global resource/lock. // (b) Go through your linked list of mounted logical volumes and for // each such volume, do the following: // (i) acquire the volume resource exclusively // (ii) invoke UDFFlushLogicalVolume() (internally) to flush the // open data streams belonging to the volume from the system // cache // (iii) Invoke the physical/virtual/logical target device object // on which the volume is mounted and inform this device // about the shutdown request (Use IoBuildSynchronouFsdRequest() // to create an IRP with MajorFunction = IRP_MJ_SHUTDOWN that you // will then issue to the target device object). // (iv) Wait for the completion of the shutdown processing by the target // device object // (v) Release the VCB resource we will have acquired in (i) above. // Acquire GlobalDataResource UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE); // Walk through all of the Vcb's attached to the global data. Link = UDFGlobalData.VCBQueue.Flink; while (Link != &(UDFGlobalData.VCBQueue)) { // Get 'next' Vcb Vcb = CONTAINING_RECORD( Link, VCB, NextVCB ); // Move to the next link now since the current Vcb may be deleted. Link = Link->Flink; ASSERT(Link != Link->Flink); if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_SHUTDOWN)) { #ifdef UDF_DELAYED_CLOSE UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE); KdPrint((" UDFCommonShutdown: set UDF_VCB_FLAGS_NO_DELAYED_CLOSE\n")); Vcb->VCBFlags |= UDF_VCB_FLAGS_NO_DELAYED_CLOSE; UDFReleaseResource(&(Vcb->VCBResource)); #endif //UDF_DELAYED_CLOSE // Note: UDFCloseAllDelayed() doesn't acquire DelayedCloseResource if // GlobalDataResource is already acquired. Thus for now we should // release GlobalDataResource and re-acquire it later. UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) ); if(Vcb->RootDirFCB && Vcb->RootDirFCB->FileInfo) { KdPrint((" UDFCommonShutdown: UDFCloseAllSystemDelayedInDir\n")); RC = UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo); ASSERT(OS_SUCCESS(RC)); } #ifdef UDF_DELAYED_CLOSE UDFCloseAllDelayed(Vcb); // UDFReleaseResource(&(UDFGlobalData.DelayedCloseResource)); #endif //UDF_DELAYED_CLOSE // re-acquire GlobalDataResource UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE); // disable Eject Waiter UDFStopEjectWaiter(Vcb); // Acquire Vcb resource UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE); ASSERT(!Vcb->OverflowQueueCount); if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_SHUTDOWN)) { UDFDoDismountSequence(Vcb, Buf, FALSE); if(Vcb->VCBFlags & UDF_VCB_FLAGS_REMOVABLE_MEDIA) { // let drive flush all data before reset delay.QuadPart = -10000000; // 1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay); } Vcb->VCBFlags |= (UDF_VCB_FLAGS_SHUTDOWN | UDF_VCB_FLAGS_VOLUME_READ_ONLY); } UDFReleaseResource(&(Vcb->VCBResource)); } } // Once we have processed all the mounted logical volumes, we can release // all acquired global resources and leave (in peace :-) UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) ); RC = STATUS_SUCCESS; try_exit: NOTHING; } _SEH2_FINALLY { if(Buf) MyFreePool__(Buf); if(!_SEH2_AbnormalTermination()) { Irp->IoStatus.Status = RC; Irp->IoStatus.Information = 0; // Free up the Irp Context UDFReleaseIrpContext(PtrIrpContext); // complete the IRP IoCompleteRequest(Irp, IO_DISK_INCREMENT); } } _SEH2_END; // end of "__finally" processing return(RC); } // end UDFCommonShutdown()
/* Thisd routine truncates DirIndex array */ OSSTATUS UDFDirIndexTrunc( IN PDIR_INDEX_HDR* _hDirNdx, IN uint_di d // decrement ) { uint_di j,k; if(d > UDF_DIR_INDEX_FRAME) { OSSTATUS status; while(d) { k = (d > UDF_DIR_INDEX_FRAME) ? UDF_DIR_INDEX_FRAME : d; if(!OS_SUCCESS(status = UDFDirIndexTrunc(_hDirNdx, k))) { return status; } d -= k; } return STATUS_SUCCESS; } PDIR_INDEX_HDR hDirNdx = *_hDirNdx; PDIR_INDEX_ITEM* FrameList; j = UDF_DIR_INDEX_FRAME+hDirNdx->LastFrameCount-d; FrameList = (PDIR_INDEX_ITEM*)(hDirNdx+1); k = hDirNdx->FrameCount-1; if(j <= UDF_DIR_INDEX_FRAME) { // free last frame if(!k && (j < 2)) { // someone tries to trunc. residual entries... return STATUS_INVALID_PARAMETER; } MyFreePool__(FrameList[k]); FrameList[k] = NULL; hDirNdx->LastFrameCount = UDF_DIR_INDEX_FRAME; hDirNdx->FrameCount--; // Truncate new last frame if(!MyReallocPool__((int8*)(FrameList[k-1]), UDF_DIR_INDEX_FRAME*sizeof(DIR_INDEX_ITEM), (int8**)(&(FrameList[k-1])), AlignDirIndex(j)*sizeof(DIR_INDEX_ITEM) ) ) return STATUS_INSUFFICIENT_RESOURCES; hDirNdx->LastFrameCount = j; // Truncate header if(!MyReallocPool__((int8*)hDirNdx, sizeof(DIR_INDEX_HDR) + (k+1)*sizeof(PDIR_INDEX_ITEM), (int8**)(&hDirNdx), sizeof(DIR_INDEX_HDR) + k*sizeof(PDIR_INDEX_ITEM) ) ) return STATUS_INSUFFICIENT_RESOURCES; (*_hDirNdx) = hDirNdx; } else { j -= UDF_DIR_INDEX_FRAME; if(!k && (j < 2)) { // someone tries to trunc. residual entries... return STATUS_INVALID_PARAMETER; } if(!MyReallocPool__((int8*)(FrameList[k]), AlignDirIndex(hDirNdx->LastFrameCount)*sizeof(DIR_INDEX_ITEM), (int8**)(&(FrameList[k])), AlignDirIndex(j)*sizeof(DIR_INDEX_ITEM) ) ) return STATUS_INSUFFICIENT_RESOURCES; hDirNdx->LastFrameCount = j; } return STATUS_SUCCESS; } // end UDFDirIndexTrunc()