ProjectArcade
1378 строк · 59.9 Кб
1#if !(NET10 || NET11 || NET20 || NET30 || NET35 || NET40 )2#define NET45_OR_GREATER3#endif4
5#if NET45_OR_GREATER && !(NET45 )6#define NET451_OR_GREATER7#endif8
9using System;10using System.Collections.Generic;11using System.Diagnostics;12using System.Diagnostics.Contracts;13using System.IO;14using System.Linq;15using System.Runtime.InteropServices;16using System.Security.AccessControl;17using System.Text;18
19using DokanNet.Logging;20using DokanNet.Native;21
22using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;23
24namespace DokanNet25{
26/// <summary>27/// The dokan operation proxy.28/// </summary>29internal sealed class DokanOperationProxy30{31#region Delegates32
33public delegate NtStatus ZwCreateFileDelegate(34[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,35IntPtr securityContext,36uint rawDesiredAccess,37uint rawFileAttributes,38uint rawShareAccess,39uint rawCreateDisposition,40uint rawCreateOptions,41[MarshalAs(UnmanagedType.LPStruct), In, Out] DokanFileInfo dokanFileInfo);42
43public delegate void CleanupDelegate(44[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,45[MarshalAs(UnmanagedType.LPStruct), In, Out] DokanFileInfo rawFileInfo);46
47public delegate void CloseFileDelegate(48[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,49[MarshalAs(UnmanagedType.LPStruct), In, Out] DokanFileInfo rawFileInfo);50
51public delegate NtStatus ReadFileDelegate(52[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,53IntPtr rawBuffer,54uint rawBufferLength,55ref int rawReadLength,56long rawOffset,57[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);58
59public delegate NtStatus WriteFileDelegate(60[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,61IntPtr rawBuffer,62uint rawNumberOfBytesToWrite,63ref int rawNumberOfBytesWritten,64long rawOffset,65[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);66
67public delegate NtStatus FlushFileBuffersDelegate(68[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,69[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);70
71public delegate NtStatus GetFileInformationDelegate(72[MarshalAs(UnmanagedType.LPWStr)] string fileName,73ref BY_HANDLE_FILE_INFORMATION handleFileInfo,74[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo fileInfo);75
76public delegate NtStatus FindFilesDelegate(77[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,78IntPtr rawFillFindData,79[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);80
81public delegate NtStatus FindFilesWithPatternDelegate(82[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,83[MarshalAs(UnmanagedType.LPWStr)] string rawSearchPattern,84IntPtr rawFillFindData,85[MarshalAs(UnmanagedType.LPStruct), In, Out] DokanFileInfo rawFileInfo);86
87public delegate NtStatus SetFileAttributesDelegate(88[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,89uint rawAttributes,90[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);91
92public delegate NtStatus SetFileTimeDelegate(93[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,94ref FILETIME rawCreationTime,95ref FILETIME rawLastAccessTime,96ref FILETIME rawLastWriteTime,97[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);98
99public delegate NtStatus DeleteFileDelegate(100[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,101[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);102
103public delegate NtStatus DeleteDirectoryDelegate(104[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,105[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);106
107public delegate NtStatus MoveFileDelegate(108[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,109[MarshalAs(UnmanagedType.LPWStr)] string rawNewFileName,110[MarshalAs(UnmanagedType.Bool)] bool rawReplaceIfExisting,111[MarshalAs(UnmanagedType.LPStruct), In, Out] DokanFileInfo rawFileInfo);112
113public delegate NtStatus SetEndOfFileDelegate(114[MarshalAs(UnmanagedType.LPWStr)] string rawFileName, long rawByteOffset,115[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);116
117public delegate NtStatus SetAllocationSizeDelegate(118[MarshalAs(UnmanagedType.LPWStr)] string rawFileName, long rawLength,119[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);120
121public delegate NtStatus LockFileDelegate(122[MarshalAs(UnmanagedType.LPWStr)] string rawFileName, long rawByteOffset, long rawLength,123[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);124
125public delegate NtStatus UnlockFileDelegate(126[MarshalAs(UnmanagedType.LPWStr)] string rawFileName, long rawByteOffset, long rawLength,127[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);128
129public delegate NtStatus GetDiskFreeSpaceDelegate(130ref long rawFreeBytesAvailable, ref long rawTotalNumberOfBytes, ref long rawTotalNumberOfFreeBytes,131[MarshalAs(UnmanagedType.LPStruct), In] DokanFileInfo rawFileInfo);132
133public delegate NtStatus GetVolumeInformationDelegate(134[MarshalAs(UnmanagedType.LPWStr)] StringBuilder rawVolumeNameBuffer,135uint rawVolumeNameSize,136ref uint rawVolumeSerialNumber,137ref uint rawMaximumComponentLength,138ref FileSystemFeatures rawFileSystemFlags,139[MarshalAs(UnmanagedType.LPWStr)] StringBuilder rawFileSystemNameBuffer,140uint rawFileSystemNameSize,141[MarshalAs(UnmanagedType.LPStruct), In] DokanFileInfo rawFileInfo);142
143public delegate NtStatus GetFileSecurityDelegate(144[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,145[In] ref SECURITY_INFORMATION rawRequestedInformation,146IntPtr rawSecurityDescriptor,147uint rawSecurityDescriptorLength,148ref uint rawSecurityDescriptorLengthNeeded,149[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);150
151public delegate NtStatus SetFileSecurityDelegate(152[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,153[In] ref SECURITY_INFORMATION rawSecurityInformation,154IntPtr rawSecurityDescriptor,155uint rawSecurityDescriptorLength,156[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);157
158/// <summary>159/// Retrieve all FileStreams informations on the file.160/// This is only called if <see cref="DokanOptions.AltStream"/> is enabled.161/// </summary>162/// <remarks>Supported since 0.8.0.163/// You must specify the version at <see cref="DOKAN_OPTIONS.Version"/>.</remarks>164/// <param name="rawFileName">Filename</param>165/// <param name="rawFillFindData">A <see cref="IntPtr"/> to a <see cref="FILL_FIND_STREAM_DATA"/>.</param>166/// <param name="rawFileInfo">A <see cref="DokanFileInfo"/>.</param>167/// <returns></returns>168public delegate NtStatus FindStreamsDelegate(169[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,170IntPtr rawFillFindData,171IntPtr findStreamContext,172[MarshalAs(UnmanagedType.LPStruct), In /*, Out*/] DokanFileInfo rawFileInfo);173
174public delegate NtStatus MountedDelegate(175[MarshalAs(UnmanagedType.LPWStr)] string rawFileName,176[MarshalAs(UnmanagedType.LPStruct), In] DokanFileInfo rawFileInfo);177
178public delegate NtStatus UnmountedDelegate(179[MarshalAs(UnmanagedType.LPStruct), In] DokanFileInfo rawFileInfo);180
181#endregion Delegates182
183private readonly IDokanOperations operations;184
185private readonly ILogger logger;186
187private readonly uint serialNumber;188
189#region Enum masks190/// <summary>191/// To be used to mask out the <see cref="FileOptions"/> flags from what is returned192/// from <see cref="Native.NativeMethods.DokanMapKernelToUserCreateFileFlags"/>.193/// </summary>194private const int FileOptionsMask =195(int)196( FileOptions.Asynchronous | FileOptions.DeleteOnClose | FileOptions.Encrypted197| FileOptions.None | FileOptions.RandomAccess | FileOptions.SequentialScan198| FileOptions.WriteThrough);199
200/// <summary>201/// To be used to mask out the <see cref="FileAttributes"/> flags from what is returned202/// from <see cref="Native.NativeMethods.DokanMapKernelToUserCreateFileFlags"/>.203/// Note that some flags where introduces in .NET Framework 4.5, and is not supported204/// in .NET Framework 4.205/// </summary>206private const int FileAttributeMask =207(int)208( FileAttributes.ReadOnly | FileAttributes.Hidden | FileAttributes.System209| FileAttributes.Directory | FileAttributes.Archive | FileAttributes.Device210| FileAttributes.Normal | FileAttributes.Temporary | FileAttributes.SparseFile211| FileAttributes.ReparsePoint | FileAttributes.Compressed | FileAttributes.Offline212| FileAttributes.NotContentIndexed | FileAttributes.Encrypted213#if NET45_OR_GREATER214// | FileAttributes.IntegrityStream | FileAttributes.NoScrubData215#endif216);217
218/// <summary>219/// To be used to mask out the <see cref="FileAccess"/> flags.220/// </summary>221private const long FileAccessMask =222(uint)223( FileAccess.ReadData | FileAccess.WriteData | FileAccess.AppendData224| FileAccess.ReadExtendedAttributes | FileAccess.WriteExtendedAttributes | FileAccess.Execute225| FileAccess.DeleteChild | FileAccess.ReadAttributes | FileAccess.WriteAttributes226| FileAccess.Delete | FileAccess.ReadPermissions | FileAccess.ChangePermissions227| FileAccess.SetOwnership | FileAccess.Synchronize | FileAccess.AccessSystemSecurity228| FileAccess.MaximumAllowed | FileAccess.GenericAll | FileAccess.GenericExecute229| FileAccess.GenericWrite | FileAccess.GenericRead);230
231/// <summary>232/// To be used to mask out the <see cref="FileShare"/> flags.233/// </summary>234private const int FileShareMask =235(int)236( FileShare.ReadWrite | FileShare.Delete | FileShare.Inheritable);237#endregion238
239/// <summary>240/// Initializes a new instance of the <see cref="DokanOperationProxy"/> class.241/// </summary>242/// <param name="operations">243/// A <see cref="IDokanOperations"/> that contains the custom implementation of the driver.244/// </param>245/// <param name="logger">246/// A <see cref="ILogger"/> that handle all logging.247/// </param>248public DokanOperationProxy(ILogger logger, IDokanOperations operations)249{250this.logger = logger;251this.operations = operations;252serialNumber = (uint)operations.GetHashCode();253}254
255/// <summary>256/// CreateFile is called each time a request is made on a file system object.257///258/// In case <see cref="FileMode.OpenOrCreate"/> and259/// <see cref="FileMode.Create"/> are opening successfully a already260/// existing file, you have to return <see cref="DokanResult.AlreadyExists"/> instead of <see cref="NtStatus.Success"/>.261///262/// If the file is a directory, CreateFile is also called.263/// In this case, CreateFile should return <see cref="NtStatus.Success"/> when that directory264/// can be opened and <see cref="DokanFileInfo.IsDirectory"/> has to be set to <c>true</c>.265///266/// <see cref="DokanFileInfo.Context"/> can be used to store data (like <see cref="FileStream"/>)267/// that can be retrieved in all other request related to the context.268/// </summary>269/// <param name="rawFileName">File path requested by the Kernel on the FileSystem.</param>270/// <param name="securityContext">SecurityContext, see <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff550613(v=vs.85).aspx">IO_SECURITY_CONTEXT structure (MSDN)</a>.</param>271/// <param name="rawDesiredAccess">Specifies an <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff540466(v=vs.85).aspx">ACCESS_MASK (MSDN)</a> value that determines the requested access to the object.</param>272/// <param name="rawFileAttributes">Specifies one or more FILE_ATTRIBUTE_XXX flags, which represent the file attributes to set if you create or overwrite a file.</param>273/// <param name="rawShareAccess">Type of share access, which is specified as zero or any combination of <see cref="FileShare"/>.</param>274/// <param name="rawCreateDisposition">Specifies the action to perform if the file does or does not exist.</param>275/// <param name="rawCreateOptions">Specifies the options to apply when the driver creates or opens the file.</param>276/// <param name="rawFileInfo">>An <see cref="DokanFileInfo"/> with information about the file or directory.</param>277/// <returns>The <see cref="NtStatus"/>.</returns>278/// \see <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff566424(v=vs.85).aspx">ZwCreateFile routine (MSDN)</a>279/// <see cref="DokanNet.IDokanOperations.CreateFile"/>280public NtStatus ZwCreateFileProxy(281string rawFileName,282IntPtr securityContext,283uint rawDesiredAccess,284uint rawFileAttributes,285uint rawShareAccess,286uint rawCreateDisposition,287uint rawCreateOptions,288DokanFileInfo rawFileInfo)289{290try291{292var fileAttributesAndFlags = 0;293var creationDisposition = 0;294var outDesiredAccess = 0u;295NativeMethods.DokanMapKernelToUserCreateFileFlags(296rawDesiredAccess,297rawFileAttributes,298rawCreateOptions,299rawCreateDisposition,300ref outDesiredAccess,301ref fileAttributesAndFlags,302ref creationDisposition);303
304var fileAttributes = (FileAttributes)(fileAttributesAndFlags & FileAttributeMask);305var fileOptions = (FileOptions )(fileAttributesAndFlags & FileOptionsMask);306var desiredAccess = (FileAccess )(outDesiredAccess & FileAccessMask);307var shareAccess = (FileShare )(rawShareAccess & FileShareMask);308
309if (logger.DebugEnabled)310{311logger.Debug("CreateFileProxy : {0}", rawFileName);312logger.Debug("\tCreationDisposition\t{0}", (FileMode)creationDisposition);313logger.Debug("\tFileAccess\t{0}", (FileAccess)rawDesiredAccess);314logger.Debug("\tFileShare\t{0}", (FileShare)rawShareAccess);315logger.Debug("\tFileOptions\t{0}", fileOptions);316logger.Debug("\tFileAttributes\t{0}", fileAttributes);317logger.Debug("\tContext\t{0}", rawFileInfo);318}319
320var result = operations.CreateFile(321rawFileName,322desiredAccess,323shareAccess,324(FileMode)creationDisposition,325fileOptions,326fileAttributes,327rawFileInfo);328
329if (logger.DebugEnabled) logger.Debug("CreateFileProxy : {0} Return : {1}", rawFileName, result);330return result;331}332catch (Exception ex)333{334logger.Error("CreateFileProxy : {0} Throw : {1}", rawFileName, ex.Message);335return DokanResult.Unsuccessful;336}337}338
339////340
341public void CleanupProxy(string rawFileName, DokanFileInfo rawFileInfo)342{343try344{345if (logger.DebugEnabled)346{347logger.Debug("CleanupProxy : {0}", rawFileName);348logger.Debug("\tContext\t{0}", rawFileInfo);349}350
351operations.Cleanup(rawFileName, rawFileInfo);352
353if (logger.DebugEnabled) logger.Debug("CleanupProxy : {0}", rawFileName);354}355catch (Exception ex)356{357logger.Error("CleanupProxy : {0} Throw : {1}", rawFileName, ex.Message);358}359}360
361////362
363public void CloseFileProxy(string rawFileName, DokanFileInfo rawFileInfo)364{365try366{367if (logger.DebugEnabled)368{369logger.Debug("CloseFileProxy : {0}", rawFileName);370logger.Debug("\tContext\t{0}", rawFileInfo);371}372
373operations.CloseFile(rawFileName, rawFileInfo);374
375if (logger.DebugEnabled) logger.Debug("CloseFileProxy : {0}", rawFileName);376}377catch (Exception ex)378{379logger.Error("CloseFileProxy : {0} Throw : {1}", rawFileName, ex.Message);380}381finally382{383rawFileInfo.Context = null;384}385}386
387////388
389public NtStatus ReadFileProxy(390string rawFileName,391IntPtr rawBuffer,392uint rawBufferLength,393ref int rawReadLength,394long rawOffset,395DokanFileInfo rawFileInfo)396{397try398{399if (logger.DebugEnabled)400{401logger.Debug("ReadFileProxy : " + rawFileName);402logger.Debug("\tBufferLength\t" + rawBufferLength);403logger.Debug("\tOffset\t" + rawOffset);404logger.Debug("\tContext\t" + rawFileInfo);405}406
407// Check if the file system has implemented the unsafe Dokan interface.408// If so, pass the raw IntPtr through instead of marshalling.409NtStatus result;410if (operations is IDokanOperationsUnsafe)411{412IDokanOperationsUnsafe unsafeOperations = operations as IDokanOperationsUnsafe;413result = unsafeOperations.ReadFile(rawFileName, rawBuffer, rawBufferLength, out rawReadLength, rawOffset, rawFileInfo);414}415else416{417// Pool the read buffer and return it to the pool when we're done with it.418byte[] buffer = BufferPool.Default.RentBuffer(rawBufferLength, logger);419try420{421result = operations.ReadFile(rawFileName, buffer, out rawReadLength, rawOffset, rawFileInfo);422Marshal.Copy(buffer, 0, rawBuffer, (int)rawBufferLength);423}424finally425{426BufferPool.Default.ReturnBuffer(buffer, logger);427}428}429
430if (logger.DebugEnabled) logger.Debug("ReadFileProxy : " + rawFileName + " Return : " + result + " ReadLength : " + rawReadLength);431return result;432}433catch (Exception ex)434{435logger.Error("ReadFileProxy : {0} Throw : {1}", rawFileName, ex.Message);436return DokanResult.InvalidParameter;437}438}439
440////441
442public NtStatus WriteFileProxy(443string rawFileName,444IntPtr rawBuffer,445uint rawNumberOfBytesToWrite,446ref int rawNumberOfBytesWritten,447long rawOffset,448DokanFileInfo rawFileInfo)449{450try451{452if (logger.DebugEnabled)453{454logger.Debug("WriteFileProxy : {0}", rawFileName);455logger.Debug("\tNumberOfBytesToWrite\t{0}", rawNumberOfBytesToWrite);456logger.Debug("\tOffset\t{0}", rawOffset);457logger.Debug("\tContext\t{0}", rawFileInfo);458}459
460// Check if the file system has implemented the unsafe Dokan interface.461// If so, pass the raw IntPtr through instead of marshalling.462NtStatus result;463if (operations is IDokanOperationsUnsafe)464{465IDokanOperationsUnsafe unsafeOperations = operations as IDokanOperationsUnsafe;466result = unsafeOperations.WriteFile(rawFileName, rawBuffer, rawNumberOfBytesToWrite, out rawNumberOfBytesWritten, rawOffset, rawFileInfo);467}468else469{470// Pool the write buffer and return it to the pool when we're done with it.471byte[] buffer = BufferPool.Default.RentBuffer(rawNumberOfBytesToWrite, logger);472try473{474Marshal.Copy(rawBuffer, buffer, 0, (int)rawNumberOfBytesToWrite);475result = operations.WriteFile(476rawFileName,477buffer,478out rawNumberOfBytesWritten,479rawOffset,480rawFileInfo);481}482finally483{484BufferPool.Default.ReturnBuffer(buffer, logger);485}486}487
488if (logger.DebugEnabled)489{490logger.Debug(491"WriteFileProxy : {0} Return : {1} NumberOfBytesWritten : {2}",492rawFileName,493result,494rawNumberOfBytesWritten);495}496
497return result;498}499catch (Exception ex)500{501logger.Error("WriteFileProxy : {0} Throw : {1}", rawFileName, ex.Message);502return DokanResult.InvalidParameter;503}504}505
506////507
508public NtStatus FlushFileBuffersProxy(string rawFileName, DokanFileInfo rawFileInfo)509{510try511{512if (logger.DebugEnabled)513{514logger.Debug("FlushFileBuffersProxy : {0}", rawFileName);515logger.Debug("\tContext\t{0}", rawFileInfo);516}517
518var result = operations.FlushFileBuffers(rawFileName, rawFileInfo);519
520if (logger.DebugEnabled) logger.Debug("FlushFileBuffersProxy : {0} Return : {1}", rawFileName, result);521return result;522}523catch (Exception ex)524{525logger.Error("FlushFileBuffersProxy : {0} Throw : {1}", rawFileName, ex.Message);526return DokanResult.InvalidParameter;527}528}529
530////531
532public NtStatus GetFileInformationProxy(533string rawFileName,534ref BY_HANDLE_FILE_INFORMATION rawHandleFileInformation,535DokanFileInfo rawFileInfo)536{537try538{539if (logger.DebugEnabled)540{541logger.Debug("GetFileInformationProxy : {0}", rawFileName);542logger.Debug("\tContext\t{0}", rawFileInfo);543}544
545FileInformation fi;546var result = operations.GetFileInformation(rawFileName, out fi, rawFileInfo);547
548if (result == DokanResult.Success)549{550Debug.Assert(fi.FileName != null, "FileName must not be null");551if (logger.DebugEnabled)552{553logger.Debug("\tFileName\t{0}", fi.FileName);554logger.Debug("\tAttributes\t{0}", fi.Attributes);555logger.Debug("\tCreationTime\t{0}", fi.CreationTime);556logger.Debug("\tLastAccessTime\t{0}", fi.LastAccessTime);557logger.Debug("\tLastWriteTime\t{0}", fi.LastWriteTime);558logger.Debug("\tLength\t{0}", fi.Length);559}560
561rawHandleFileInformation.dwFileAttributes = (uint)fi.Attributes /* + FILE_ATTRIBUTE_VIRTUAL*/;562
563var ctime = ToFileTime(fi.CreationTime);564var atime = ToFileTime(fi.LastAccessTime);565var mtime = ToFileTime(fi.LastWriteTime);566rawHandleFileInformation.ftCreationTime.dwHighDateTime = (int)(ctime >> 32);567rawHandleFileInformation.ftCreationTime.dwLowDateTime = (int)(ctime & 0xffffffff);568
569rawHandleFileInformation.ftLastAccessTime.dwHighDateTime = (int)(atime >> 32);570rawHandleFileInformation.ftLastAccessTime.dwLowDateTime = (int)(atime & 0xffffffff);571
572rawHandleFileInformation.ftLastWriteTime.dwHighDateTime = (int)(mtime >> 32);573rawHandleFileInformation.ftLastWriteTime.dwLowDateTime = (int)(mtime & 0xffffffff);574
575rawHandleFileInformation.dwVolumeSerialNumber = serialNumber;576
577rawHandleFileInformation.nFileSizeLow = (uint)(fi.Length & 0xffffffff);578rawHandleFileInformation.nFileSizeHigh = (uint)(fi.Length >> 32);579rawHandleFileInformation.dwNumberOfLinks = 1;580rawHandleFileInformation.nFileIndexHigh = 0;581rawHandleFileInformation.nFileIndexLow = (uint)(fi.FileName != null ? fi.FileName.GetHashCode() : 0);582}583
584if (logger.DebugEnabled) logger.Debug("GetFileInformationProxy : {0} Return : {1}", rawFileName, result);585return result;586}587catch (Exception ex)588{589logger.Error("GetFileInformationProxy : {0} Throw : {1}", rawFileName, ex.Message);590return DokanResult.InvalidParameter;591}592}593
594////595
596public NtStatus FindFilesProxy(string rawFileName, IntPtr rawFillFindData, DokanFileInfo rawFileInfo)597{598try599{600if (logger.DebugEnabled)601{602logger.Debug("FindFilesProxy : {0}", rawFileName);603logger.Debug("\tContext\t{0}", rawFileInfo);604}605
606IList<FileInformation> files;607var result = operations.FindFiles(rawFileName, out files, rawFileInfo);608
609Debug.Assert(files != null, "Files must not be null");610if (result == DokanResult.Success && files.Count != 0)611{612if (logger.DebugEnabled)613{614foreach (var fi in files)615{616logger.Debug("\tFileName\t{0}", fi.FileName);617logger.Debug("\t\tAttributes\t{0}", fi.Attributes);618logger.Debug("\t\tCreationTime\t{0}", fi.CreationTime);619logger.Debug("\t\tLastAccessTime\t{0}", fi.LastAccessTime);620logger.Debug("\t\tLastWriteTime\t{0}", fi.LastWriteTime);621logger.Debug("\t\tLength\t{0}", fi.Length);622}623}624
625var fill = GetDataFromPointer<FILL_FIND_FILE_DATA>(rawFillFindData);626
627// used a single entry call to speed up the "enumeration" of the list628foreach (var t in files)629{630AddTo(fill, rawFileInfo, t);631}632}633
634if (logger.DebugEnabled) logger.Debug("FindFilesProxy : {0} Return : {1}", rawFileName, result);635return result;636}637catch (Exception ex)638{639logger.Error("FindFilesProxy : {0} Throw : {1}", rawFileName, ex.Message);640return DokanResult.InvalidParameter;641}642}643
644public NtStatus FindFilesWithPatternProxy(645string rawFileName,646string rawSearchPattern,647IntPtr rawFillFindData,648DokanFileInfo rawFileInfo)649{650try651{652if (logger.DebugEnabled)653{654logger.Debug("FindFilesWithPatternProxy : {0}", rawFileName);655logger.Debug("\trawSearchPattern\t{0}", rawSearchPattern);656logger.Debug("\tContext\t{0}", rawFileInfo);657}658
659IList<FileInformation> files;660var result = operations.FindFilesWithPattern(rawFileName, rawSearchPattern, out files, rawFileInfo);661
662Debug.Assert(files != null, "Files must not be null");663if (result == DokanResult.Success && files.Any())664{665if (logger.DebugEnabled)666{667foreach (var fi in files)668{669logger.Debug("\tFileName\t{0}", fi.FileName);670logger.Debug("\t\tAttributes\t{0}", fi.Attributes);671logger.Debug("\t\tCreationTime\t{0}", fi.CreationTime);672logger.Debug("\t\tLastAccessTime\t{0}", fi.LastAccessTime);673logger.Debug("\t\tLastWriteTime\t{0}", fi.LastWriteTime);674logger.Debug("\t\tLength\t{0}", fi.Length);675}676}677
678var fill = GetDataFromPointer<FILL_FIND_FILE_DATA>(rawFillFindData);679
680// used a single entry call to speed up the "enumeration" of the list681foreach (var t in files)682{683AddTo(fill, rawFileInfo, t);684}685}686
687if (logger.DebugEnabled) logger.Debug("FindFilesWithPatternProxy : {0} Return : {1}", rawFileName, result);688return result;689}690catch (Exception ex)691{692logger.Error("FindFilesWithPatternProxy : {0} Throw : {1}", rawFileName, ex.Message);693return DokanResult.InvalidParameter;694}695}696
697/// <summary>698/// Call the delegate <paramref name="fill"/> using data in <paramref name="rawFileInfo"/> and <paramref name="fi"/>.699/// </summary>700/// <param name="fill">The delegate of type <see cref="FILL_FIND_FILE_DATA"/> to be called.</param>701/// <param name="rawFileInfo">A <see cref="DokanFileInfo"/> to be used when calling <paramref name="fill"/>.</param>702/// <param name="fi">A <see cref="FileInformation"/> with information to be used when calling <paramref name="fill"/>.</param>703private static void AddTo(FILL_FIND_FILE_DATA fill, DokanFileInfo rawFileInfo, FileInformation fi)704{705Debug.Assert(!string.IsNullOrEmpty(fi.FileName), "FileName must not be empty or null");706var ctime = ToFileTime(fi.CreationTime);707var atime = ToFileTime(fi.LastAccessTime);708var mtime = ToFileTime(fi.LastWriteTime);709var data = new WIN32_FIND_DATA710{711dwFileAttributes = fi.Attributes,712ftCreationTime =713{714dwHighDateTime = (int) (ctime >> 32),715dwLowDateTime = (int) (ctime & 0xffffffff)716},717ftLastAccessTime =718{719dwHighDateTime = (int) (atime >> 32),720dwLowDateTime = (int) (atime & 0xffffffff)721},722ftLastWriteTime =723{724dwHighDateTime = (int) (mtime >> 32),725dwLowDateTime = (int) (mtime & 0xffffffff)726},727nFileSizeLow = (uint)(fi.Length & 0xffffffff),728nFileSizeHigh = (uint)(fi.Length >> 32),729cFileName = fi.FileName730};731//ZeroMemory(&data, sizeof(WIN32_FIND_DATAW));732
733fill(ref data, rawFileInfo);734}735
736public NtStatus FindStreamsProxy(string rawFileName, IntPtr rawFillFindData, IntPtr findStreamContext, DokanFileInfo rawFileInfo)737{738try739{740if (logger.DebugEnabled)741{742logger.Debug("FindStreamsProxy: {0}", rawFileName);743logger.Debug("\tContext\t{0}", rawFileInfo);744}745
746IList<FileInformation> files;747var result = operations.FindStreams(rawFileName, out files, rawFileInfo);748
749Debug.Assert(!(result == DokanResult.NotImplemented && files == null));750if (result == DokanResult.Success && files.Count != 0)751{752if (logger.DebugEnabled)753{754foreach (var fi in files)755{756logger.Debug("\tFileName\t{0}", fi.FileName);757logger.Debug("\t\tLength\t{0}", fi.Length);758}759}760
761var fill = GetDataFromPointer<FILL_FIND_STREAM_DATA>(rawFillFindData);762
763// used a single entry call to speed up the "enumeration" of the list764bool bufferFull = false;765foreach (var t in files)766{767if (bufferFull)768{769result = NtStatus.BufferOverflow;770break;771}772bufferFull = !AddTo(fill, findStreamContext, t);773}774}775
776if (logger.DebugEnabled) logger.Debug("FindStreamsProxy : {0} Return : {1}", rawFileName, result);777return result;778}779catch (Exception ex)780{781logger.Error("FindStreamsProxy : {0} Throw : {1}", rawFileName, ex.Message);782return DokanResult.InvalidParameter;783}784}785
786/// <summary>Converts an unmanaged function pointer to a delegate of a specified type. </summary>787/// <returns>A instance of the specified delegate type.</returns>788/// <param name="rawDelegate">The unmanaged function pointer to convert. </param>789/// <typeparam name="TDelegate">The type of the delegate to return. </typeparam>790/// <exception cref="T:System.ArgumentException">The <typeparam name="TDelegate" /> generic parameter is not a delegate, or it is an open generic type.</exception>791/// <exception cref="T:System.ArgumentNullException">The <paramref name="rawDelegate" /> parameter is null.</exception>792private static TDelegate GetDataFromPointer<TDelegate>(IntPtr rawDelegate) where TDelegate : class793{794/*795#if NET451_OR_GREATER
796return Marshal.GetDelegateForFunctionPointer<TDelegate>(rawDelegate);
797#else*/
798return Marshal.GetDelegateForFunctionPointer(rawDelegate, typeof(TDelegate)) as TDelegate;799//#endif
800}801
802/// <summary>803/// Call the delegate <paramref name="fill"/> using data in <paramref name="rawFileInfo"/> and <paramref name="fi"/>.804/// </summary>805/// <param name="fill">The delegate of type <see cref="FILL_FIND_STREAM_DATA"/> to be called.</param>806/// <param name="rawFileInfo">A <see cref="DokanFileInfo"/> to be used when calling <paramref name="fill"/>.</param>807/// <param name="fi">A <see cref="FileInformation"/> with information to be used when calling <paramref name="fill"/>.</param>808/// <returns>Whether the buffer is full or not.</returns>809private static bool AddTo(FILL_FIND_STREAM_DATA fill, IntPtr findStreamContext, FileInformation fi)810{811Debug.Assert(!string.IsNullOrEmpty(fi.FileName), "FileName must not be empty or null");812var data = new WIN32_FIND_STREAM_DATA813{814StreamSize = fi.Length,815cStreamName = fi.FileName816};817//ZeroMemory(&data, sizeof(WIN32_FIND_DATAW));818
819return fill(ref data, findStreamContext);820}821
822////823
824public NtStatus SetEndOfFileProxy(string rawFileName, long rawByteOffset, DokanFileInfo rawFileInfo)825{826try827{828if (logger.DebugEnabled)829{830logger.Debug("SetEndOfFileProxy : {0}", rawFileName);831logger.Debug("\tByteOffset\t{0}", rawByteOffset);832logger.Debug("\tContext\t{0}", rawFileInfo);833}834
835var result = operations.SetEndOfFile(rawFileName, rawByteOffset, rawFileInfo);836
837if (logger.DebugEnabled) logger.Debug("SetEndOfFileProxy : {0} Return : {1}", rawFileName, result);838return result;839}840catch (Exception ex)841{842logger.Error("SetEndOfFileProxy : {0} Throw : {1}", rawFileName, ex.Message);843return DokanResult.InvalidParameter;844}845}846
847public NtStatus SetAllocationSizeProxy(string rawFileName, long rawLength, DokanFileInfo rawFileInfo)848{849try850{851if (logger.DebugEnabled)852{853logger.Debug("SetAllocationSizeProxy : {0}", rawFileName);854logger.Debug("\tLength\t{0}", rawLength);855logger.Debug("\tContext\t{0}", rawFileInfo);856}857
858var result = operations.SetAllocationSize(rawFileName, rawLength, rawFileInfo);859
860if (logger.DebugEnabled) logger.Debug("SetAllocationSizeProxy : {0} Return : {1}", rawFileName, result);861return result;862}863catch (Exception ex)864{865logger.Error("SetAllocationSizeProxy : {0} Throw : {1}", rawFileName, ex.Message);866return DokanResult.InvalidParameter;867}868}869
870////871
872public NtStatus SetFileAttributesProxy(string rawFileName, uint rawAttributes, DokanFileInfo rawFileInfo)873{874try875{876if (logger.DebugEnabled)877{878logger.Debug("SetFileAttributesProxy : {0}", rawFileName);879logger.Debug("\tAttributes\t{0}", (FileAttributes)rawAttributes);880logger.Debug("\tContext\t{0}", rawFileInfo);881}882
883var result = operations.SetFileAttributes(rawFileName, (FileAttributes)rawAttributes, rawFileInfo);884
885if (logger.DebugEnabled) logger.Debug("SetFileAttributesProxy : {0} Return : {1}", rawFileName, result);886return result;887}888catch (Exception ex)889{890logger.Error("SetFileAttributesProxy : {0} Throw : {1}", rawFileName, ex.Message);891return DokanResult.InvalidParameter;892}893}894
895////896
897public NtStatus SetFileTimeProxy(898string rawFileName,899ref FILETIME rawCreationTime,900ref FILETIME rawLastAccessTime,901ref FILETIME rawLastWriteTime,902DokanFileInfo rawFileInfo)903{904try905{906var ctime = (rawCreationTime.dwLowDateTime != 0 || rawCreationTime.dwHighDateTime != 0) &&907(rawCreationTime.dwLowDateTime != -1 || rawCreationTime.dwHighDateTime != -1)908? DateTime.FromFileTime(((long) rawCreationTime.dwHighDateTime << 32) |909(uint) rawCreationTime.dwLowDateTime)910: (DateTime?) null;911var atime = (rawLastAccessTime.dwLowDateTime != 0 || rawLastAccessTime.dwHighDateTime != 0) &&912(rawLastAccessTime.dwLowDateTime != -1 || rawLastAccessTime.dwHighDateTime != -1)913? DateTime.FromFileTime(((long) rawLastAccessTime.dwHighDateTime << 32) |914(uint) rawLastAccessTime.dwLowDateTime)915: (DateTime?) null;916var mtime = (rawLastWriteTime.dwLowDateTime != 0 || rawLastWriteTime.dwHighDateTime != 0) &&917(rawLastWriteTime.dwLowDateTime != -1 || rawLastWriteTime.dwHighDateTime != -1)918? DateTime.FromFileTime(((long) rawLastWriteTime.dwHighDateTime << 32) |919(uint) rawLastWriteTime.dwLowDateTime)920: (DateTime?) null;921
922if (logger.DebugEnabled)923{924logger.Debug("SetFileTimeProxy : {0}", rawFileName);925logger.Debug("\tCreateTime\t{0}", ctime);926logger.Debug("\tAccessTime\t{0}", atime);927logger.Debug("\tWriteTime\t{0}", mtime);928logger.Debug("\tContext\t{0}", rawFileInfo);929}930
931var result = operations.SetFileTime(rawFileName, ctime, atime, mtime, rawFileInfo);932
933if (logger.DebugEnabled) logger.Debug("SetFileTimeProxy : {0} Return : {1}", rawFileName, result);934return result;935}936catch (Exception ex)937{938logger.Error("SetFileTimeProxy : {0} Throw : {1}", rawFileName, ex.Message);939return DokanResult.InvalidParameter;940}941}942
943////944
945public NtStatus DeleteFileProxy(string rawFileName, DokanFileInfo rawFileInfo)946{947try948{949if (logger.DebugEnabled)950{951logger.Debug("DeleteFileProxy : {0}", rawFileName);952logger.Debug("\tContext\t{0}", rawFileInfo);953}954
955var result = operations.DeleteFile(rawFileName, rawFileInfo);956
957if (logger.DebugEnabled) logger.Debug("DeleteFileProxy : {0} Return : {1}", rawFileName, result);958return result;959}960catch (Exception ex)961{962logger.Error("DeleteFileProxy : {0} Throw : {1}", rawFileName, ex.Message);963return DokanResult.InvalidParameter;964}965}966
967////968
969public NtStatus DeleteDirectoryProxy(string rawFileName, DokanFileInfo rawFileInfo)970{971try972{973if (logger.DebugEnabled)974{975logger.Debug("DeleteDirectoryProxy : {0}", rawFileName);976logger.Debug("\tContext\t{0}", rawFileInfo);977}978
979var result = operations.DeleteDirectory(rawFileName, rawFileInfo);980
981if (logger.DebugEnabled) logger.Debug("DeleteDirectoryProxy : {0} Return : {1}", rawFileName, result);982return result;983}984catch (Exception ex)985{986logger.Error("DeleteDirectoryProxy : {0} Throw : {1}", rawFileName, ex.Message);987return DokanResult.InvalidParameter;988}989}990
991////992
993public NtStatus MoveFileProxy(994string rawFileName,995string rawNewFileName,996bool rawReplaceIfExisting,997DokanFileInfo rawFileInfo)998{999try1000{1001if (logger.DebugEnabled)1002{1003logger.Debug("MoveFileProxy : {0}", rawFileName);1004logger.Debug("\tNewFileName\t{0}", rawNewFileName);1005logger.Debug("\tReplaceIfExisting\t{0}", rawReplaceIfExisting);1006logger.Debug("\tContext\t{0}", rawFileInfo);1007}1008
1009var result = operations.MoveFile(rawFileName, rawNewFileName, rawReplaceIfExisting, rawFileInfo);1010
1011if (logger.DebugEnabled) logger.Debug("MoveFileProxy : {0} Return : {1}", rawFileName, result);1012return result;1013}1014catch (Exception ex)1015{1016logger.Error("MoveFileProxy : {0} Throw : {1}", rawFileName, ex.Message);1017return DokanResult.InvalidParameter;1018}1019}1020
1021////1022
1023public NtStatus LockFileProxy(string rawFileName, long rawByteOffset, long rawLength, DokanFileInfo rawFileInfo)1024{1025try1026{1027if (logger.DebugEnabled)1028{1029logger.Debug("LockFileProxy : {0}", rawFileName);1030logger.Debug("\tByteOffset\t{0}", rawByteOffset);1031logger.Debug("\tLength\t{0}", rawLength);1032logger.Debug("\tContext\t{0}", rawFileInfo);1033}1034
1035var result = operations.LockFile(rawFileName, rawByteOffset, rawLength, rawFileInfo);1036
1037if (logger.DebugEnabled) logger.Debug("LockFileProxy : {0} Return : {1}", rawFileName, result);1038return result;1039}1040catch (Exception ex)1041{1042logger.Error("LockFileProxy : {0} Throw : {1}", rawFileName, ex.Message);1043return DokanResult.InvalidParameter;1044}1045}1046
1047////1048
1049public NtStatus UnlockFileProxy(1050string rawFileName,1051long rawByteOffset,1052long rawLength,1053DokanFileInfo rawFileInfo)1054{1055try1056{1057if (logger.DebugEnabled)1058{1059logger.Debug("UnlockFileProxy : {0}", rawFileName);1060logger.Debug("\tByteOffset\t{0}", rawByteOffset);1061logger.Debug("\tLength\t{0}", rawLength);1062logger.Debug("\tContext\t{0}", rawFileInfo);1063}1064
1065var result = operations.UnlockFile(rawFileName, rawByteOffset, rawLength, rawFileInfo);1066
1067if (logger.DebugEnabled) logger.Debug("UnlockFileProxy : {0} Return : {1}", rawFileName, result);1068return result;1069}1070catch (Exception ex)1071{1072logger.Error("UnlockFileProxy : {0} Throw : {1}", rawFileName, ex.Message);1073return DokanResult.InvalidParameter;1074}1075}1076
1077////1078
1079public NtStatus GetDiskFreeSpaceProxy(1080ref long rawFreeBytesAvailable,1081ref long rawTotalNumberOfBytes,1082ref long rawTotalNumberOfFreeBytes,1083DokanFileInfo rawFileInfo)1084{1085try1086{1087if (logger.DebugEnabled)1088{1089logger.Debug("GetDiskFreeSpaceProxy:");1090logger.Debug("\tContext\t{0}", rawFileInfo);1091}1092
1093var result = operations.GetDiskFreeSpace(1094out rawFreeBytesAvailable,1095out rawTotalNumberOfBytes,1096out rawTotalNumberOfFreeBytes,1097rawFileInfo);1098
1099if (logger.DebugEnabled)1100{1101logger.Debug("\tFreeBytesAvailable\t{0}", rawFreeBytesAvailable);1102logger.Debug("\tTotalNumberOfBytes\t{0}", rawTotalNumberOfBytes);1103logger.Debug("\tTotalNumberOfFreeBytes\t{0}", rawTotalNumberOfFreeBytes);1104logger.Debug("GetDiskFreeSpaceProxy Return : {0}", result);1105}1106
1107return result;1108}1109catch (Exception ex)1110{1111logger.Error("GetDiskFreeSpaceProxy Throw : {0}", ex.Message);1112return DokanResult.InvalidParameter;1113}1114}1115
1116public NtStatus GetVolumeInformationProxy(1117StringBuilder rawVolumeNameBuffer,1118uint rawVolumeNameSize,1119ref uint rawVolumeSerialNumber,1120ref uint rawMaximumComponentLength,1121ref FileSystemFeatures rawFileSystemFlags,1122StringBuilder rawFileSystemNameBuffer,1123uint rawFileSystemNameSize,1124DokanFileInfo rawFileInfo)1125{1126rawVolumeSerialNumber = serialNumber;1127try1128{1129if (logger.DebugEnabled)1130{1131logger.Debug("GetVolumeInformationProxy:");1132logger.Debug("\tContext\t{0}", rawFileInfo);1133}1134
1135string volumeName;1136string name;1137uint maximumComponentLength;1138var result = operations.GetVolumeInformation(out volumeName, out rawFileSystemFlags, out name, out maximumComponentLength, rawFileInfo);1139
1140if (result == DokanResult.Success)1141{1142Debug.Assert(!string.IsNullOrEmpty(name), "name must not be null");1143Debug.Assert(!string.IsNullOrEmpty(volumeName), "Label must not be null");1144rawVolumeNameBuffer.Append(volumeName);1145rawFileSystemNameBuffer.Append(name);1146rawMaximumComponentLength = maximumComponentLength;1147
1148if (logger.DebugEnabled)1149{1150logger.Debug("\tVolumeNameBuffer\t{0}", rawVolumeNameBuffer);1151logger.Debug("\tFileSystemNameBuffer\t{0}", rawFileSystemNameBuffer);1152logger.Debug("\tVolumeSerialNumber\t{0}", rawVolumeSerialNumber);1153logger.Debug("\tFileSystemFlags\t{0}", rawFileSystemFlags);1154logger.Debug("\tMaximumComponentLength\t{0}", rawMaximumComponentLength);1155}1156}1157
1158if (logger.DebugEnabled) logger.Debug("GetVolumeInformationProxy Return : {0}", result);1159return result;1160}1161catch (Exception ex)1162{1163logger.Error("GetVolumeInformationProxy Throw : {0}", ex.Message);1164return DokanResult.InvalidParameter;1165}1166}1167
1168public NtStatus MountedProxy(string mountPoint, DokanFileInfo rawFileInfo)1169{1170try1171{1172if (logger.DebugEnabled)1173{1174logger.Debug("MountedProxy:");1175logger.Debug("\tMountPoint\t{0}", mountPoint);1176logger.Debug("\tContext\t{0}", rawFileInfo);1177}1178
1179var result = operations.Mounted(mountPoint, rawFileInfo);1180
1181if (logger.DebugEnabled) logger.Debug("MountedProxy Return : {0}", result);1182return result;1183}1184catch (Exception ex)1185{1186logger.Error("MountedProxy Throw : {0}", ex.Message);1187return DokanResult.InvalidParameter;1188}1189}1190
1191public NtStatus UnmountedProxy(DokanFileInfo rawFileInfo)1192{1193try1194{1195if (logger.DebugEnabled)1196{1197logger.Debug("UnmountedProxy:");1198logger.Debug("\tContext\t{0}", rawFileInfo);1199}1200
1201var result = operations.Unmounted(rawFileInfo);1202
1203if (logger.DebugEnabled) logger.Debug("UnmountedProxy Return : {0}", result);1204return result;1205}1206catch (Exception ex)1207{1208logger.Error("UnmountedProxy Throw : {0}", ex.Message);1209return DokanResult.InvalidParameter;1210}1211}1212
1213public NtStatus GetFileSecurityProxy(1214string rawFileName,1215ref SECURITY_INFORMATION rawRequestedInformation,1216IntPtr rawSecurityDescriptor,1217uint rawSecurityDescriptorLength,1218ref uint rawSecurityDescriptorLengthNeeded,1219DokanFileInfo rawFileInfo)1220{1221var sect = AccessControlSections.None;1222if (rawRequestedInformation.HasFlag(SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION))1223{1224sect |= AccessControlSections.Owner;1225}1226if (rawRequestedInformation.HasFlag(SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION))1227{1228sect |= AccessControlSections.Group;1229}1230if (rawRequestedInformation.HasFlag(SECURITY_INFORMATION.DACL_SECURITY_INFORMATION) ||1231rawRequestedInformation.HasFlag(SECURITY_INFORMATION.PROTECTED_DACL_SECURITY_INFORMATION) ||1232rawRequestedInformation.HasFlag(SECURITY_INFORMATION.UNPROTECTED_DACL_SECURITY_INFORMATION))1233{1234sect |= AccessControlSections.Access;1235}1236if (rawRequestedInformation.HasFlag(SECURITY_INFORMATION.SACL_SECURITY_INFORMATION) ||1237rawRequestedInformation.HasFlag(SECURITY_INFORMATION.PROTECTED_SACL_SECURITY_INFORMATION) ||1238rawRequestedInformation.HasFlag(SECURITY_INFORMATION.UNPROTECTED_SACL_SECURITY_INFORMATION))1239{1240sect |= AccessControlSections.Audit;1241}1242try1243{1244if (logger.DebugEnabled)1245{1246logger.Debug("GetFileSecurityProxy : {0}", rawFileName);1247logger.Debug("\tFileSystemSecurity\t{0}", sect);1248logger.Debug("\tContext\t{0}", rawFileInfo);1249}1250
1251FileSystemSecurity sec;1252var result = operations.GetFileSecurity(rawFileName, out sec, sect, rawFileInfo);1253if (result == DokanResult.Success /*&& sec != null*/)1254{1255Debug.Assert(sec != null, "sec must not be null");1256if (logger.DebugEnabled) logger.Debug("\tFileSystemSecurity Result : {0}", sec);1257var buffer = sec.GetSecurityDescriptorBinaryForm();1258rawSecurityDescriptorLengthNeeded = (uint)buffer.Length;1259if (buffer.Length > rawSecurityDescriptorLength)1260return DokanResult.BufferOverflow;1261
1262Marshal.Copy(buffer, 0, rawSecurityDescriptor, buffer.Length);1263}1264
1265if (logger.DebugEnabled) logger.Debug("GetFileSecurityProxy : {0} Return : {1}", rawFileName, result);1266return result;1267}1268catch (Exception ex)1269{1270logger.Error("GetFileSecurityProxy : {0} Throw : {1}", rawFileName, ex.Message);1271return DokanResult.InvalidParameter;1272}1273}1274
1275public NtStatus SetFileSecurityProxy(1276string rawFileName,1277ref SECURITY_INFORMATION rawSecurityInformation,1278IntPtr rawSecurityDescriptor,1279uint rawSecurityDescriptorLength,1280DokanFileInfo rawFileInfo)1281{1282var sect = AccessControlSections.None;1283if (rawSecurityInformation.HasFlag(SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION))1284{1285sect |= AccessControlSections.Owner;1286}1287if (rawSecurityInformation.HasFlag(SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION))1288{1289sect |= AccessControlSections.Group;1290}1291if (rawSecurityInformation.HasFlag(SECURITY_INFORMATION.DACL_SECURITY_INFORMATION) ||1292rawSecurityInformation.HasFlag(SECURITY_INFORMATION.PROTECTED_DACL_SECURITY_INFORMATION) ||1293rawSecurityInformation.HasFlag(SECURITY_INFORMATION.UNPROTECTED_DACL_SECURITY_INFORMATION))1294{1295sect |= AccessControlSections.Access;1296}1297if (rawSecurityInformation.HasFlag(SECURITY_INFORMATION.SACL_SECURITY_INFORMATION) ||1298rawSecurityInformation.HasFlag(SECURITY_INFORMATION.PROTECTED_SACL_SECURITY_INFORMATION) ||1299rawSecurityInformation.HasFlag(SECURITY_INFORMATION.UNPROTECTED_SACL_SECURITY_INFORMATION))1300{1301sect |= AccessControlSections.Audit;1302}1303var buffer = new byte[rawSecurityDescriptorLength];1304try1305{1306Marshal.Copy(rawSecurityDescriptor, buffer, 0, (int)rawSecurityDescriptorLength);1307var sec = rawFileInfo.IsDirectory ? (FileSystemSecurity)new DirectorySecurity() : new FileSecurity();1308sec.SetSecurityDescriptorBinaryForm(buffer);1309
1310if (logger.DebugEnabled)1311{1312logger.Debug("SetFileSecurityProxy : {0}", rawFileName);1313logger.Debug("\tAccessControlSections\t{0}", sect);1314logger.Debug("\tFileSystemSecurity\t{0}", sec);1315logger.Debug("\tContext\t{0}", rawFileInfo);1316}1317
1318var result = operations.SetFileSecurity(rawFileName, sec, sect, rawFileInfo);1319
1320if (logger.DebugEnabled) logger.Debug("SetFileSecurityProxy : {0} Return : {1}", rawFileName, result);1321return result;1322}1323catch (Exception ex)1324{1325logger.Error("SetFileSecurityProxy : {0} Throw : {1}", rawFileName, ex.Message);1326return DokanResult.InvalidParameter;1327}1328}1329
1330/// <summary>1331/// Converts the value of <paramref name="dateTime"/> to a Windows file time.1332/// If <paramref name="dateTime"/> is <c>null</c> or before 12:00 midnight January 1, 1601 C.E. UTC, it returns <c>0</c>.1333/// </summary>1334/// <param name="dateTime">1335/// The date Time.1336/// </param>1337/// <returns>1338/// The value of <paramref name="dateTime"/> expressed as a Windows file time1339/// -or- it returns <c>0</c> if <paramref name="dateTime"/> is before 12:00 midnight January 1, 1601 C.E. UTC or <c>null</c>.1340/// </returns>1341/// \see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa365739(v=vs.85).aspx">WIN32_FILE_ATTRIBUTE_DATA structure (MSDN)</a>1342[Pure]1343private static long ToFileTime(DateTime? dateTime)1344{1345return dateTime.HasValue && (dateTime.Value >= DateTime.FromFileTime(0))1346? dateTime.Value.ToFileTime()1347: 0;1348}1349
1350#region Nested type: FILL_FIND_FILE_DATA1351
1352/// <summary>1353/// Used to add an entry in <see cref="DokanOperationProxy.FindFilesProxy"/> and <see cref="DokanOperationProxy.FindFilesWithPatternProxy"/>.1354/// </summary>1355/// <param name="rawFindData">A <see cref="WIN32_FIND_DATA"/>.</param>1356/// <param name="rawFileInfo">A <see cref="DokanFileInfo"/>.</param>1357/// <returns><c>1</c> if buffer is full, otherwise <c>0</c> (currently it never returns <c>1</c>)</returns>1358/// <remarks>This is the same delegate as <c>PFillFindData</c> (dokan.h) in the C version of Dokan.</remarks>1359private delegate long FILL_FIND_FILE_DATA(1360ref WIN32_FIND_DATA rawFindData, [MarshalAs(UnmanagedType.LPStruct), In] DokanFileInfo rawFileInfo);1361
1362#endregion Nested type: FILL_FIND_FILE_DATA1363
1364#region Nested type: FILL_FIND_STREAM_DATA1365
1366/// <summary>1367/// Used to add an entry in <see cref="DokanOperationProxy.FindStreamsProxy"/>.1368/// </summary>1369/// <param name="rawFindData">A <see cref="WIN32_FIND_STREAM_DATA"/>.</param>1370/// <param name="findStreamContext">The context received by <see cref="DOKAN_OPERATIONS.FindStreams"/>.</param>1371/// <returns><c>FALSE</c> if the buffer is full, otherwise <c>TRUE</c></returns>1372/// <remarks>This is the same delegate as <c>PFillFindStreamData</c> (dokan.h) in the C version of Dokan.</remarks>1373private delegate bool FILL_FIND_STREAM_DATA(1374ref WIN32_FIND_STREAM_DATA rawFindData, IntPtr findStreamContext);1375
1376#endregion Nested type: FILL_FIND_STREAM_DATA1377}1378}