示例#1
0
        /// <summary>
        /// Set the desired file allocation, preferably without changing the end of file.
        /// </summary>
        /// <param name="length">the size to set, in bytes</param>
        /// <param name="useNT">if true, use the low-level undocumented NT API to allocate, without setting the length</param>
        private void SetAllocation(long length, bool useNT)
        {
            // using NT calls seems unreliable, beyond being undocumented, unsupported, and
            // likely platform dependant.
            //
            // Sometimes, it works perfectly. Other times, it generates roughly the same
            // number of fragments as not doing anything (but can vary). Other times, it
            // generates 10 times as many fragments as not doing anything.
            //
            // It does, at least, leave the file without extra allocated space at all times.

#if !NT_ALLOCATE
            if (!useNT)
            {
                base.SetLength(length);
            }
            else
            {
#endif
            //FILE_ALLOCATION_INFORMATION allocInfo = new FILE_ALLOCATION_INFORMATION(length);
            long allocInfo = length;
            IOUtil.Win32.IO_STATUS_BLOCK status = new IOUtil.Win32.IO_STATUS_BLOCK();      // = IO_STATUS_BLOCK.NullBlock;
            IOUtil.Win32.NtSetInformationFile(
                base.SafeFileHandle.DangerousGetHandle(),
                ref status,
                ref allocInfo,
                8,     //sizeof(FILE_ALLOCATION_INFORMATION),
                IOUtil.Win32.FILE_INFORMATION_CLASS.FileAllocationInformation);
            // FILE_INFORMATION_CLASS.FileEndOfFileInformation);
#if !NT_ALLOCATE
        }
#endif
        }
示例#2
0
		/// <summary>
		/// Get the named streams present in the given file.
		/// </summary>
		/// <param name="fileName">the file to inspect</param>
		/// <returns>the list of named streams available for the file, excluding the default stream</returns>
		/// <remarks>
		/// <p>
		/// An empty string array will be returned if there are any errors or if
		/// no named streams exist.
		/// </p>
		/// </remarks>
		public static string[] GetNamedStreams(string fileName)
		{
			IntPtr handle = IntPtr.Zero;
			try
			{
				handle = IOUtil.Win32.CreateFile(
					fileName,
					IOUtil.Win32.FileAccess.GENERIC_READ,
					IOUtil.Win32.FileShare.FILE_SHARE_READ | IOUtil.Win32.FileShare.FILE_SHARE_WRITE,
					IntPtr.Zero,
					IOUtil.Win32.CreationDisposition.OPEN_EXISTING,
					IOUtil.Win32.FileFlagsAndAttributes.FILE_FLAG_BACKUP_SEMANTICS,
					IntPtr.Zero);
				//if (handle == IntPtr.Zero)  return new string[0];
				if (handle.ToInt64() <= 0) return new string[0];

				byte[] streamNames = new byte[32768 << 2];
				IOUtil.Win32.IO_STATUS_BLOCK statusBlock = new IOUtil.Win32.IO_STATUS_BLOCK();

				uint status = IOUtil.Win32.NtQueryInformationFile(handle, ref statusBlock,
					streamNames, (uint)streamNames.Length, IOUtil.Win32.FILE_INFORMATION_CLASS.FileStreamInformation);

				if (!IOUtil.Win32.NT_SUCCESS(status) || statusBlock.Information == 0) return new string[0];

				ArrayList names = new ArrayList();
				for (int pos = 0; pos < streamNames.Length; )
				{
					try
					{
						int start = pos;
						// get next entry:
						int next = (int)BitConverter.ToUInt32(streamNames, pos);
						pos += 4;
						// get length:
						int len = (int)BitConverter.ToUInt32(streamNames, pos);
						pos += 4;
						// get size:
						long size = BitConverter.ToInt64(streamNames, pos);
						pos += 8;
						// get allocation size:
						long allocationSize = BitConverter.ToInt64(streamNames, pos);
						pos += 8;
						// get name:
						string name = Encoding.Unicode.GetString(streamNames, pos, len);

						if (name.Length != 0)
						{
							if (name[0] == ':' && name.EndsWith(":$DATA"))
							{
								name = name.Substring(1, name.Length - "::$DATA".Length);
							}
							if (name.Length != 0)
							{
								names.Add(name);
							}
						}

						if (next == 0) break;
						pos = start + next;
						//		private struct FILE_STREAM_INFORMATION
						//		{
						//			ULONG    	        NextEntry;
						//			ULONG    	        NameLength;
						//			LARGE_INTEGER    	Size;
						//			LARGE_INTEGER    	AllocationSize;
						//			USHORT    	        Name[1];
						//		}
					}
					catch
					{
						// ignore running off the end??
					}
				}

				return (string[])names.ToArray(typeof(string));
			}
			catch
			{
				return new string[0];
			}
			finally
			{
				if (handle != IntPtr.Zero)
				{
					try
					{
						IOUtil.Win32.CloseHandle(handle);
					}
					catch
					{
						// ignore...
					}
				}
			}
		}
		/// <summary>
		/// Set the desired file allocation, preferably without changing the end of file.
		/// </summary>
		/// <param name="length">the size to set, in bytes</param>
		/// <param name="useNT">if true, use the low-level undocumented NT API to allocate, without setting the length</param>
		private void SetAllocation(long length, bool useNT)
		{
			// using NT calls seems unreliable, beyond being undocumented, unsupported, and
			// likely platform dependant.
			//
			// Sometimes, it works perfectly. Other times, it generates roughly the same
			// number of fragments as not doing anything (but can vary). Other times, it
			// generates 10 times as many fragments as not doing anything.
			//
			// It does, at least, leave the file without extra allocated space at all times.

#if !NT_ALLOCATE
			if (!useNT)
			{
				base.SetLength(length);
			}
			else
			{
#endif
				//FILE_ALLOCATION_INFORMATION allocInfo = new FILE_ALLOCATION_INFORMATION(length);
				long allocInfo = length;
				IOUtil.Win32.IO_STATUS_BLOCK status = new IOUtil.Win32.IO_STATUS_BLOCK();  // = IO_STATUS_BLOCK.NullBlock;
				IOUtil.Win32.NtSetInformationFile(
#if DOTNET2
					base.SafeFileHandle.DangerousGetHandle(),
#else
					base.Handle,
#endif
					ref status,
					ref allocInfo,
					8, //sizeof(FILE_ALLOCATION_INFORMATION),
					IOUtil.Win32.FILE_INFORMATION_CLASS.FileAllocationInformation);
					// FILE_INFORMATION_CLASS.FileEndOfFileInformation);
#if !NT_ALLOCATE
			}
#endif
		}