NTSTATUS DokanSetDispositionInformation( PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { PFILE_DISPOSITION_INFORMATION dispositionInfo = (PFILE_DISPOSITION_INFORMATION)((PCHAR)EventContext + EventContext->Operation.SetFile.BufferOffset); if (!DokanOperations->DeleteFile || !DokanOperations->DeleteDirectory) return STATUS_NOT_IMPLEMENTED; if (!dispositionInfo->DeleteFile) { return STATUS_SUCCESS; } if (FileInfo->IsDirectory) { return DokanOperations->DeleteDirectory( EventContext->Operation.SetFile.FileName, FileInfo); } else { return DokanOperations->DeleteFile( EventContext->Operation.SetFile.FileName, FileInfo); } }
NTSTATUS DokanSetAllocationInformation( PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { PFILE_ALLOCATION_INFORMATION allocInfo = (PFILE_ALLOCATION_INFORMATION)((PCHAR)EventContext + EventContext->Operation.SetFile.BufferOffset); // A file's allocation size and end-of-file position are independent of each other, // with the following exception: The end-of-file position must always be less than // or equal to the allocation size. If the allocation size is set to a value that // is less than the end-of-file position, the end-of-file position is automatically // adjusted to match the allocation size. if (DokanOperations->SetAllocationSize) { return DokanOperations->SetAllocationSize( EventContext->Operation.SetFile.FileName, allocInfo->AllocationSize.QuadPart, FileInfo); } // How can we check the current end-of-file position? if (allocInfo->AllocationSize.QuadPart == 0) { return DokanOperations->SetEndOfFile( EventContext->Operation.SetFile.FileName, allocInfo->AllocationSize.QuadPart, FileInfo); } else { DbgPrint(" SetAllocationInformation %I64d, can't handle this parameter.\n", allocInfo->AllocationSize.QuadPart); } return STATUS_SUCCESS; }
NTSTATUS DokanSetRenameInformation( PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { PDOKAN_RENAME_INFORMATION renameInfo = (PDOKAN_RENAME_INFORMATION)((PCHAR)EventContext + EventContext->Operation.SetFile.BufferOffset); WCHAR newName[MAX_PATH]; ZeroMemory(newName, sizeof(newName)); if (renameInfo->FileName[0] != L'\\') { ULONG pos; for (pos = EventContext->Operation.SetFile.FileNameLength / sizeof(WCHAR); pos != 0; --pos) { if (EventContext->Operation.SetFile.FileName[pos] == '\\') break; } RtlCopyMemory(newName, EventContext->Operation.SetFile.FileName, (pos + 1)*sizeof(WCHAR)); RtlCopyMemory((PCHAR)newName + (pos+1)*sizeof(WCHAR), renameInfo->FileName, renameInfo->FileNameLength); } else { RtlCopyMemory(newName, renameInfo->FileName, renameInfo->FileNameLength); } if (!DokanOperations->MoveFile) return STATUS_NOT_IMPLEMENTED; return DokanOperations->MoveFile( EventContext->Operation.SetFile.FileName, newName, renameInfo->ReplaceIfExists, FileInfo); }
NTSTATUS DokanFsFullSizeInformation(PEVENT_INFORMATION EventInfo, PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { ULONGLONG freeBytesAvailable = 0; ULONGLONG totalBytes = 0; ULONGLONG freeBytes = 0; NTSTATUS status = STATUS_NOT_IMPLEMENTED; ULONG allocationUnitSize = FileInfo->DokanOptions->AllocationUnitSize; ULONG sectorSize = FileInfo->DokanOptions->SectorSize; PFILE_FS_FULL_SIZE_INFORMATION sizeInfo = (PFILE_FS_FULL_SIZE_INFORMATION)EventInfo->Buffer; if (EventContext->Operation.Volume.BufferLength < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) { return STATUS_BUFFER_OVERFLOW; } if (DokanOperations->GetDiskFreeSpace) { status = DokanOperations->GetDiskFreeSpace( &freeBytesAvailable, // FreeBytesAvailable &totalBytes, // TotalNumberOfBytes &freeBytes, // TotalNumberOfFreeBytes FileInfo); } if (status == STATUS_NOT_IMPLEMENTED) { status = DokanGetDiskFreeSpace(&freeBytesAvailable, // FreeBytesAvailable &totalBytes, // TotalNumberOfBytes &freeBytes, // TotalNumberOfFreeBytes FileInfo); } if (status != STATUS_SUCCESS) { return status; } sizeInfo->TotalAllocationUnits.QuadPart = totalBytes / allocationUnitSize; sizeInfo->ActualAvailableAllocationUnits.QuadPart = freeBytes / allocationUnitSize; sizeInfo->CallerAvailableAllocationUnits.QuadPart = freeBytesAvailable / allocationUnitSize; sizeInfo->SectorsPerAllocationUnit = allocationUnitSize / sectorSize; sizeInfo->BytesPerSector = sectorSize; EventInfo->BufferLength = sizeof(FILE_FS_FULL_SIZE_INFORMATION); return STATUS_SUCCESS; }
NTSTATUS DokanSetBasicInformation( PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { FILETIME creation, lastAccess, lastWrite; NTSTATUS status = STATUS_NOT_IMPLEMENTED; PFILE_BASIC_INFORMATION basicInfo = (PFILE_BASIC_INFORMATION)((PCHAR)EventContext + EventContext->Operation.SetFile.BufferOffset); if (!DokanOperations->SetFileAttributes) return STATUS_NOT_IMPLEMENTED; if (!DokanOperations->SetFileTime) return STATUS_NOT_IMPLEMENTED; status = DokanOperations->SetFileAttributes( EventContext->Operation.SetFile.FileName, basicInfo->FileAttributes, FileInfo); if (status > 0) return status; creation.dwLowDateTime = basicInfo->CreationTime.LowPart; creation.dwHighDateTime = basicInfo->CreationTime.HighPart; lastAccess.dwLowDateTime = basicInfo->LastAccessTime.LowPart; lastAccess.dwHighDateTime = basicInfo->LastAccessTime.HighPart; lastWrite.dwLowDateTime = basicInfo->LastWriteTime.LowPart; lastWrite.dwHighDateTime = basicInfo->LastWriteTime.HighPart; return DokanOperations->SetFileTime( EventContext->Operation.SetFile.FileName, &creation, &lastAccess, &lastWrite, FileInfo); }
NTSTATUS DokanSetValidDataLengthInformation( PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { PFILE_VALID_DATA_LENGTH_INFORMATION validInfo = (PFILE_VALID_DATA_LENGTH_INFORMATION)((PCHAR)EventContext + EventContext->Operation.SetFile.BufferOffset); if (!DokanOperations->SetEndOfFile) return STATUS_NOT_IMPLEMENTED; return DokanOperations->SetEndOfFile( EventContext->Operation.SetFile.FileName, validInfo->ValidDataLength.QuadPart, FileInfo); }
NTSTATUS DokanSetEndOfFileInformation( PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { PFILE_END_OF_FILE_INFORMATION endInfo = (PFILE_END_OF_FILE_INFORMATION)((PCHAR)EventContext + EventContext->Operation.SetFile.BufferOffset); if (!DokanOperations->SetEndOfFile) return STATUS_NOT_IMPLEMENTED; return DokanOperations->SetEndOfFile( EventContext->Operation.SetFile.FileName, endInfo->EndOfFile.QuadPart, FileInfo); }
ULONG DokanFsFullSizeInformation( PEVENT_INFORMATION EventInfo, PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { ULONGLONG freeBytesAvailable = 0; ULONGLONG totalBytes = 0; ULONGLONG freeBytes = 0; int status = -1; PFILE_FS_FULL_SIZE_INFORMATION sizeInfo = (PFILE_FS_FULL_SIZE_INFORMATION)EventInfo->Buffer; if (!DokanOperations->GetDiskFreeSpace) { DokanOperations->GetDiskFreeSpace = DokanGetDiskFreeSpace; //return STATUS_NOT_IMPLEMENTED; } if (EventContext->Operation.Volume.BufferLength < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) { return STATUS_BUFFER_OVERFLOW; } status = DokanOperations->GetDiskFreeSpace( &freeBytesAvailable, // FreeBytesAvailable &totalBytes, // TotalNumberOfBytes &freeBytes, // TotalNumberOfFreeBytes FileInfo); if (status < 0) { return STATUS_INVALID_PARAMETER; } sizeInfo->TotalAllocationUnits.QuadPart = totalBytes / DOKAN_ALLOCATION_UNIT_SIZE; sizeInfo->ActualAvailableAllocationUnits.QuadPart = freeBytes / DOKAN_ALLOCATION_UNIT_SIZE; sizeInfo->CallerAvailableAllocationUnits.QuadPart = freeBytesAvailable / DOKAN_ALLOCATION_UNIT_SIZE; sizeInfo->SectorsPerAllocationUnit = DOKAN_ALLOCATION_UNIT_SIZE / DOKAN_SECTOR_SIZE; sizeInfo->BytesPerSector = DOKAN_SECTOR_SIZE; EventInfo->BufferLength = sizeof(FILE_FS_FULL_SIZE_INFORMATION); return STATUS_SUCCESS; }
NTSTATUS DokanFsVolumeInformation(PEVENT_INFORMATION EventInfo, PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { WCHAR volumeName[MAX_PATH]; DWORD volumeSerial = 0; DWORD maxComLength = 0; DWORD fsFlags = 0; WCHAR fsName[MAX_PATH]; ULONG remainingLength; ULONG bytesToCopy; NTSTATUS status = STATUS_NOT_IMPLEMENTED; PFILE_FS_VOLUME_INFORMATION volumeInfo = (PFILE_FS_VOLUME_INFORMATION)EventInfo->Buffer; remainingLength = EventContext->Operation.Volume.BufferLength; if (remainingLength < sizeof(FILE_FS_VOLUME_INFORMATION)) { return STATUS_BUFFER_OVERFLOW; } RtlZeroMemory(volumeName, sizeof(volumeName)); RtlZeroMemory(fsName, sizeof(fsName)); if (DokanOperations->GetVolumeInformation) { status = DokanOperations->GetVolumeInformation( volumeName, // VolumeNameBuffer sizeof(volumeName) / sizeof(WCHAR), // VolumeNameSize &volumeSerial, // VolumeSerialNumber &maxComLength, // MaximumComponentLength &fsFlags, // FileSystemFlags fsName, // FileSystemNameBuffer sizeof(fsName) / sizeof(WCHAR), // FileSystemNameSize FileInfo); } if (status == STATUS_NOT_IMPLEMENTED) { status = DokanGetVolumeInformation( volumeName, // VolumeNameBuffer sizeof(volumeName) / sizeof(WCHAR), // VolumeNameSize &volumeSerial, // VolumeSerialNumber &maxComLength, // MaximumComponentLength &fsFlags, // FileSystemFlags fsName, // FileSystemNameBuffer sizeof(fsName) / sizeof(WCHAR), // FileSystemNameSize FileInfo); } if (status != STATUS_SUCCESS) { return status; } volumeInfo->VolumeCreationTime.QuadPart = 0; volumeInfo->VolumeSerialNumber = volumeSerial; volumeInfo->SupportsObjects = FALSE; remainingLength -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]); bytesToCopy = (ULONG)wcslen(volumeName) * sizeof(WCHAR); if (remainingLength < bytesToCopy) { bytesToCopy = remainingLength; } volumeInfo->VolumeLabelLength = bytesToCopy; RtlCopyMemory(volumeInfo->VolumeLabel, volumeName, bytesToCopy); remainingLength -= bytesToCopy; EventInfo->BufferLength = EventContext->Operation.Volume.BufferLength - remainingLength; return STATUS_SUCCESS; }
ULONG DokanFsAttributeInformation( PEVENT_INFORMATION EventInfo, PEVENT_CONTEXT EventContext, PDOKAN_FILE_INFO FileInfo, PDOKAN_OPERATIONS DokanOperations) { WCHAR volumeName[MAX_PATH]; DWORD volumeSerial; DWORD maxComLength; DWORD fsFlags; WCHAR fsName[MAX_PATH]; ULONG remainingLength; ULONG bytesToCopy; int status = -1; PFILE_FS_ATTRIBUTE_INFORMATION attrInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)EventInfo->Buffer; if (!DokanOperations->GetVolumeInformation) { DokanOperations->GetVolumeInformation = DokanGetVolumeInformation; //return STATUS_NOT_IMPLEMENTED; } remainingLength = EventContext->Operation.Volume.BufferLength; if (remainingLength < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) { return STATUS_BUFFER_OVERFLOW; } RtlZeroMemory(volumeName, sizeof(volumeName)); RtlZeroMemory(fsName, sizeof(fsName)); status = DokanOperations->GetVolumeInformation( volumeName, // VolumeNameBuffer sizeof(volumeName) / sizeof(WCHAR), // VolumeNameSize &volumeSerial, // VolumeSerialNumber &maxComLength, // MaximumComponentLength &fsFlags, // FileSystemFlags fsName, // FileSystemNameBuffer sizeof(fsName) / sizeof(WCHAR), // FileSystemNameSize FileInfo); if (status < 0) { return STATUS_INVALID_PARAMETER; } attrInfo->FileSystemAttributes = fsFlags; attrInfo->MaximumComponentNameLength = maxComLength; remainingLength -= FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName[0]); bytesToCopy = (ULONG)wcslen(fsName) * sizeof(WCHAR); if (remainingLength < bytesToCopy) { bytesToCopy = remainingLength; } attrInfo->FileSystemNameLength = bytesToCopy; RtlCopyMemory(attrInfo->FileSystemName, fsName, bytesToCopy); remainingLength -= bytesToCopy; EventInfo->BufferLength = EventContext->Operation.Volume.BufferLength - remainingLength; return STATUS_SUCCESS; }