private static NativeMethods.FILE_STREAM_INFORMATION[] GetADSes(SafeFileHandle FileHandle) { NativeMethods.IO_STATUS_BLOCK status; IntPtr fileInfoPtr = IntPtr.Zero; try { NativeMethods.FILE_STREAM_INFORMATION streamInfo = new NativeMethods.FILE_STREAM_INFORMATION(); int fileInfoPtrLength = (Marshal.SizeOf(streamInfo) + 32768) / 2; uint ntStatus = 0; do { fileInfoPtrLength *= 2; if (fileInfoPtr != IntPtr.Zero) { Marshal.FreeHGlobal(fileInfoPtr); } fileInfoPtr = Marshal.AllocHGlobal(fileInfoPtrLength); ntStatus = NativeMethods.NtQueryInformationFile(FileHandle, out status, fileInfoPtr, (uint)fileInfoPtrLength, NativeMethods.FILE_INFORMATION_CLASS.FileStreamInformation); }while (ntStatus != 0 /*STATUS_SUCCESS*/ && ntStatus == 0x80000005 /*STATUS_BUFFER_OVERFLOW*/); //Marshal the structure manually (argh!) List <NativeMethods.FILE_STREAM_INFORMATION> result = new List <NativeMethods.FILE_STREAM_INFORMATION>(); unsafe { for (byte *i = (byte *)fileInfoPtr; streamInfo.NextEntryOffset != 0; i += streamInfo.NextEntryOffset) { byte *currStreamPtr = i; streamInfo.NextEntryOffset = *(uint *)currStreamPtr; currStreamPtr += sizeof(uint); streamInfo.StreamNameLength = *(uint *)currStreamPtr; currStreamPtr += sizeof(uint); streamInfo.StreamSize = *(long *)currStreamPtr; currStreamPtr += sizeof(long); streamInfo.StreamAllocationSize = *(long *)currStreamPtr; currStreamPtr += sizeof(long); streamInfo.StreamName = Marshal.PtrToStringUni((IntPtr)currStreamPtr, (int)streamInfo.StreamNameLength / 2); result.Add(streamInfo); } } return(result.ToArray()); } finally { Marshal.FreeHGlobal(fileInfoPtr); } }
private static NativeMethods.FILE_STREAM_INFORMATION[] GetADSes(SafeFileHandle FileHandle) { NativeMethods.IO_STATUS_BLOCK status = new NativeMethods.IO_STATUS_BLOCK(); IntPtr fileInfoPtr = IntPtr.Zero; try { NativeMethods.FILE_STREAM_INFORMATION streamInfo = new NativeMethods.FILE_STREAM_INFORMATION(); int fileInfoPtrLength = (Marshal.SizeOf(streamInfo) + 32768) / 2; uint ntStatus = 0; do { fileInfoPtrLength *= 2; if (fileInfoPtr != IntPtr.Zero) Marshal.FreeHGlobal(fileInfoPtr); fileInfoPtr = Marshal.AllocHGlobal(fileInfoPtrLength); ntStatus = NativeMethods.NtQueryInformationFile(FileHandle, ref status, fileInfoPtr, (uint)fileInfoPtrLength, NativeMethods.FILE_INFORMATION_CLASS.FileStreamInformation); } while (ntStatus != 0 && ntStatus == 0x80000005 ); List<NativeMethods.FILE_STREAM_INFORMATION> result = new List<NativeMethods.FILE_STREAM_INFORMATION>(); unsafe { for (byte* i = (byte*)fileInfoPtr; streamInfo.NextEntryOffset != 0; i += streamInfo.NextEntryOffset) { byte* currStreamPtr = i; streamInfo.NextEntryOffset = *(uint*)currStreamPtr; currStreamPtr += sizeof(uint); streamInfo.StreamNameLength = *(uint*)currStreamPtr; currStreamPtr += sizeof(uint); streamInfo.StreamSize = *(long*)currStreamPtr; currStreamPtr += sizeof(long); streamInfo.StreamAllocationSize = *(long*)currStreamPtr; currStreamPtr += sizeof(long); streamInfo.StreamName = Marshal.PtrToStringUni((IntPtr)currStreamPtr, (int)streamInfo.StreamNameLength / 2); result.Add(streamInfo); } } return result.ToArray(); } finally { Marshal.FreeHGlobal(fileInfoPtr); } }