+IOBufferMemoryDescriptor *
+IOBufferMemoryDescriptor::withCopy(
+ task_t inTask,
+ IOOptionBits options,
+ vm_map_t sourceMap,
+ mach_vm_address_t source,
+ mach_vm_size_t size)
+{
+ IOBufferMemoryDescriptor * inst;
+ kern_return_t err;
+ vm_map_copy_t copy;
+ vm_map_address_t address;
+
+ copy = NULL;
+ do {
+ err = kIOReturnNoMemory;
+ inst = new IOBufferMemoryDescriptor;
+ if (!inst) {
+ break;
+ }
+ inst->_ranges.v64 = IONew(IOAddressRange, 1);
+ if (!inst->_ranges.v64) {
+ break;
+ }
+
+ err = vm_map_copyin(sourceMap, source, size,
+ false /* src_destroy */, ©);
+ if (KERN_SUCCESS != err) {
+ break;
+ }
+
+ err = vm_map_copyout(get_task_map(inTask), &address, copy);
+ if (KERN_SUCCESS != err) {
+ break;
+ }
+ copy = NULL;
+
+ inst->_ranges.v64->address = address;
+ inst->_ranges.v64->length = size;
+
+ if (!inst->initWithPhysicalMask(inTask, options, size, page_size, 0)) {
+ err = kIOReturnError;
+ }
+ } while (false);
+
+ if (KERN_SUCCESS == err) {
+ return inst;
+ }
+
+ if (copy) {
+ vm_map_copy_discard(copy);
+ }
+ OSSafeReleaseNULL(inst);
+ return NULL;
+}
+
+