There are three ways of describing allocated memory in WDF: Buffers, WDF Memory Objects, and MDLs.
A memory buffer in WDF is just want it is in any system: A pointer and a length. You get a “buffer” directly when you call functions such as WdfRequestRetrieveInputBuffer (or friends) or when you use one of the WDM functions such as ExAllocatePoolWithTag.
A buffer isn’t an object. It’s just some allocated memory. The buffer itself is not managed by the Framework. Now, don’t confuse this with an object (such as a WDFREQUEST) which might own a buffer and therefore manage its lifetime. If you consider JUST THE BUFFER, the buffer itself is not Framework managed.
Contrast this with a WDF Memory object. A WDF Memory object is an opaque object that is used to describe a buffer. That buffer might be associated with a Request, in which case you can call WdfRequestRetrieveInputMemory (or friends) or it may simply be associated with a private allocation from one of the Pools (created with WdfMemoryCreate).
Just like with any WDF Object, Memory objects are managed by the Framework. They have a reference count, they can have a context, they can have cleanup callback methods…. anything that any other WDF Object has.
Because it’s simple to get a buffer (pointer and length) from a WDF Memory object, in many cases a WDFMEMORY object merely offers a convenient way to allocate and track memory allocations using the same programming pattern by which you do ANY work in the Framework.
WDF Memory Objects also provide a handy way to pass along a description of a buffer for use by another WDF method. An added bonus is that if the function does something with a lifetime, the function can reference the WDF Memory objectto ensure it’s not deallocated while being accessed.
By the way… a related structure that folks often find confusing is the WDF_MEMORY_DESCRIPTOR. This is just a data structure, not a WDF Object. It provides a uniform way to describe a memory area… regardless of whether you currently track and describe that memory area using a buffer, a WDF Memory Object, or and MDL. While folks often see this structure as an annoyance (like when building USB Requests) it’s *really* a convenience, because it allows you to use ANY of the three possible types of memory descriptors to describe a data area, instead of having to use a specific one.