public static NTStatus SetFileInformation(INTFileStore fileStore, object handle, SetInformation information)
 {
     if (information is SetFileBasicInfo)
     {
         SetFileBasicInfo     basicInfo     = (SetFileBasicInfo)information;
         FileBasicInformation fileBasicInfo = new FileBasicInformation();
         fileBasicInfo.CreationTime   = basicInfo.CreationTime;
         fileBasicInfo.LastAccessTime = basicInfo.LastAccessTime;
         fileBasicInfo.LastWriteTime  = basicInfo.LastWriteTime;
         fileBasicInfo.ChangeTime     = basicInfo.LastChangeTime;
         fileBasicInfo.FileAttributes = (FileAttributes)basicInfo.ExtFileAttributes;
         fileBasicInfo.Reserved       = basicInfo.Reserved;
         return(fileStore.SetFileInformation(handle, fileBasicInfo));
     }
     else if (information is SetFileDispositionInfo)
     {
         FileDispositionInformation fileDispositionInfo = new FileDispositionInformation();
         fileDispositionInfo.DeletePending = ((SetFileDispositionInfo)information).DeletePending;
         return(fileStore.SetFileInformation(handle, fileDispositionInfo));
     }
     else if (information is SetFileAllocationInfo)
     {
         // This information level is used to set the file length in bytes.
         // Note: the input will NOT be a multiple of the cluster size / bytes per sector.
         FileAllocationInformation fileAllocationInfo = new FileAllocationInformation();
         fileAllocationInfo.AllocationSize = ((SetFileAllocationInfo)information).AllocationSize;
         return(fileStore.SetFileInformation(handle, fileAllocationInfo));
     }
     else if (information is SetFileEndOfFileInfo)
     {
         FileEndOfFileInformation fileEndOfFileInfo = new FileEndOfFileInformation();
         fileEndOfFileInfo.EndOfFile = ((SetFileEndOfFileInfo)information).EndOfFile;
         return(fileStore.SetFileInformation(handle, fileEndOfFileInfo));
     }
     else
     {
         return(NTStatus.STATUS_NOT_IMPLEMENTED);
     }
 }
        internal static Transaction2SetFileInformationResponse GetSubcommandResponse(SMBHeader header, Transaction2SetFileInformationRequest subcommand, FileSystemShare share, StateObject state)
        {
            string openedFilePath = state.GetOpenedFilePath(subcommand.FID);

            if (openedFilePath == null)
            {
                header.Status = NTStatus.STATUS_INVALID_HANDLE;
                return(null);
            }

            Transaction2SetFileInformationResponse response = new Transaction2SetFileInformationResponse();

            switch (subcommand.InformationLevel)
            {
            case SetInformationLevel.SMB_INFO_STANDARD:
            {
                return(response);
            }

            case SetInformationLevel.SMB_INFO_SET_EAS:
            {
                throw new NotImplementedException();
            }

            case SetInformationLevel.SMB_SET_FILE_BASIC_INFO:
            {
                string userName = state.GetConnectedUserName(header.UID);
                if (!share.HasWriteAccess(userName))
                {
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }

                SetFileBasicInfo info       = (SetFileBasicInfo)subcommand.SetInfo;
                bool             isHidden   = (info.ExtFileAttributes & ExtendedFileAttributes.Hidden) > 0;
                bool             isReadonly = (info.ExtFileAttributes & ExtendedFileAttributes.Readonly) > 0;
                bool             isArchived = (info.ExtFileAttributes & ExtendedFileAttributes.Archive) > 0;
                try
                {
                    share.FileSystem.SetAttributes(openedFilePath, isHidden, isReadonly, isArchived);
                }
                catch (UnauthorizedAccessException)
                {
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }

                DateTime?creationTime   = null;
                DateTime?lastWriteDT    = null;
                DateTime?lastAccessTime = null;
                if (info.CreationTime != SMBHelper.FileTimeNotSpecified)
                {
                    creationTime = info.CreationTime;
                }
                if (info.LastWriteTime != SMBHelper.FileTimeNotSpecified)
                {
                    lastWriteDT = info.LastWriteTime;
                }
                if (info.LastAccessTime != SMBHelper.FileTimeNotSpecified)
                {
                    lastAccessTime = info.LastAccessTime;
                }

                try
                {
                    share.FileSystem.SetDates(openedFilePath, creationTime, lastWriteDT, lastAccessTime);
                }
                catch (IOException ex)
                {
                    ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                    if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                    {
                        // Returning STATUS_SHARING_VIOLATION is undocumented but apparently valid
                        header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                        return(null);
                    }
                    else
                    {
                        header.Status = NTStatus.STATUS_DATA_ERROR;
                        return(null);
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }
                return(response);
            }

            case SetInformationLevel.SMB_SET_FILE_DISPOSITION_INFO:
            {
                if (((SetFileDispositionInfo)subcommand.SetInfo).DeletePending)
                {
                    // We're supposed to delete the file on close, but it's too late to report errors at this late stage
                    string userName = state.GetConnectedUserName(header.UID);
                    if (!share.HasWriteAccess(userName))
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(null);
                    }

                    try
                    {
                        share.FileSystem.Delete(openedFilePath);
                    }
                    catch (IOException)
                    {
                        header.Status = NTStatus.STATUS_FILE_LOCK_CONFLICT;
                        return(null);
                    }
                    catch (UnauthorizedAccessException)
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(null);
                    }
                }
                return(response);
            }

            case SetInformationLevel.SMB_SET_FILE_ALLOCATION_INFO:
            {
                // This subcommand is used to set the file length in bytes.
                // Note: the input will NOT be a multiple of the cluster size / bytes per sector.
                ulong allocationSize = ((SetFileAllocationInfo)subcommand.SetInfo).AllocationSize;
                try
                {
                    Stream stream = share.FileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                    stream.SetLength((long)allocationSize);
                    stream.Close();
                }
                catch
                {
                }
                return(response);
            }

            case SetInformationLevel.SMB_SET_FILE_END_OF_FILE_INFO:
            {
                ulong endOfFile = ((SetFileEndOfFileInfo)subcommand.SetInfo).EndOfFile;
                try
                {
                    Stream stream = share.FileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                    stream.SetLength((long)endOfFile);
                    stream.Close();
                }
                catch
                {
                }
                return(response);
            }

            default:
            {
                throw new InvalidRequestException();
            }
            }
        }