Hi GavH,
I checked Marshal.FreeCoTaskMem method in MSDN document - http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.marshal.freecotaskmem(vs.80).aspx and found Windows Vista wasn't included in the support platform in .NET Framework 2.0 ( Windows 98, Windows 2000 SP4, Windows CE, Windows Millennium Edition, Windows Mobile for Pocket PC, Windows Mobile for Smartphone, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition).
The reason why only Vista is failing is most probably because vista has become more sensitive (or robust) to such kind of allocation differences.
Here is a thread discussion about "Access memory error after unmanaged interop in Vista" which is close to what you need for your reference - http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1677959&SiteID=1
Hope this helps,
Citizens on the earth
The FreeCoTaskMem(pDib) call inside the try block is unecessary since you're calling it again in the finally block. It's also buggy since it doesn't zero out the pointer afterwards.
The FreeCoTaskMem(bmpPtr) call shouldn't be there since bmpPtr doesn't point to a separately allocated buffer but to an offset inside the pDib buffer.
And finally, IntPtr.Size returns the size in bytes, so it's either 4 or 8, never 32.