static NTSTATUS DOKAN_CALLBACK MirrorSetFileAttributes( LPCWSTR FileName, DWORD FileAttributes, PDOKAN_FILE_INFO DokanFileInfo) { UNREFERENCED_PARAMETER(DokanFileInfo); WCHAR filePath[MAX_PATH]; GetFilePath(filePath, MAX_PATH, FileName); DbgPrint(L"SetFileAttributes %s\n", filePath); if (!SetFileAttributes(filePath, FileAttributes)) { DWORD error = GetLastError(); DbgPrint(L"\terror code = %d\n\n", error); return ToNtStatus(error); } DbgPrint(L"\n"); return STATUS_SUCCESS; }
static NTSTATUS DOKAN_CALLBACK MirrorGetFileInformation( LPCWSTR FileName, LPBY_HANDLE_FILE_INFORMATION HandleFileInformation, PDOKAN_FILE_INFO DokanFileInfo) { WCHAR filePath[MAX_PATH]; HANDLE handle = (HANDLE)DokanFileInfo->Context; BOOL opened = FALSE; GetFilePath(filePath, MAX_PATH, FileName); DbgPrint(L"GetFileInfo : %s\n", filePath); if (!handle || handle == INVALID_HANDLE_VALUE) { DbgPrint(L"\tinvalid handle\n\n"); // If CreateDirectory returned FILE_ALREADY_EXISTS and // it is called with FILE_OPEN_IF, that handle must be opened. handle = CreateFile(filePath, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); DbgPrint(L"GetFileInfo failed(%d)\n", error); return ToNtStatus(error); } opened = TRUE; } if (!GetFileInformationByHandle(handle, HandleFileInformation)) { DbgPrint(L"\terror code = %d\n", GetLastError()); if (opened) { opened = FALSE; CloseHandle(handle); } // FileName is a root directory // in this case, FindFirstFile can't get directory information if (wcslen(FileName) == 1) { DbgPrint(L" root dir\n"); HandleFileInformation->dwFileAttributes = GetFileAttributes(filePath); } else { WIN32_FIND_DATAW find; ZeroMemory(&find, sizeof(WIN32_FIND_DATAW)); HANDLE findHandle = FindFirstFile(filePath, &find); if (findHandle == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); DbgPrint(L"\tFindFirstFile error code = %d\n\n", error); return ToNtStatus(error); } HandleFileInformation->dwFileAttributes = find.dwFileAttributes; HandleFileInformation->ftCreationTime = find.ftCreationTime; HandleFileInformation->ftLastAccessTime = find.ftLastAccessTime; HandleFileInformation->ftLastWriteTime = find.ftLastWriteTime; HandleFileInformation->nFileSizeHigh = find.nFileSizeHigh; HandleFileInformation->nFileSizeLow = find.nFileSizeLow; DbgPrint(L"\tFindFiles OK, file size = %d\n", find.nFileSizeLow); FindClose(findHandle); } } else { DbgPrint(L"\tGetFileInformationByHandle success, file size = %d\n", HandleFileInformation->nFileSizeLow); } DbgPrint(L"\n"); if (opened) { CloseHandle(handle); } return STATUS_SUCCESS; }
static NTSTATUS DOKAN_CALLBACK MirrorWriteFile(LPCWSTR FileName, LPCVOID Buffer, DWORD NumberOfBytesToWrite, LPDWORD NumberOfBytesWritten, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo) { WCHAR filePath[MAX_PATH]; HANDLE handle = (HANDLE)DokanFileInfo->Context; ULONG offset = (ULONG)Offset; BOOL opened = FALSE; GetFilePath(filePath, MAX_PATH, FileName); DbgPrint(L"WriteFile : %s, offset %I64d, length %d\n", filePath, Offset, NumberOfBytesToWrite); // reopen the file if (!handle || handle == INVALID_HANDLE_VALUE) { DbgPrint(L"\tinvalid handle, cleanuped?\n"); handle = CreateFile(filePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); DbgPrint(L"\tCreateFile error : %d\n\n", error); return ToNtStatus(error); } opened = TRUE; } LARGE_INTEGER distanceToMove; distanceToMove.QuadPart = Offset; if (DokanFileInfo->WriteToEndOfFile) { LARGE_INTEGER z; z.QuadPart = 0; if (!SetFilePointerEx(handle, z, NULL, FILE_END)) { DWORD error = GetLastError(); DbgPrint(L"\tseek error, offset = EOF, error = %d\n", error); if (opened) CloseHandle(handle); return ToNtStatus(error); } } else if (!SetFilePointerEx(handle, distanceToMove, NULL, FILE_BEGIN)) { DWORD error = GetLastError(); DbgPrint(L"\tseek error, offset = %d, error = %d\n", offset, error); if (opened) CloseHandle(handle); return ToNtStatus(error); } if (!WriteFile(handle, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, NULL)) { DWORD error = GetLastError(); DbgPrint(L"\twrite error = %u, buffer length = %d, write length = %d\n", error, NumberOfBytesToWrite, *NumberOfBytesWritten); if (opened) CloseHandle(handle); return ToNtStatus(error); } else { DbgPrint(L"\twrite %d, offset %d\n\n", *NumberOfBytesWritten, offset); } // close the file when it is reopened if (opened) CloseHandle(handle); return STATUS_SUCCESS; }
static NTSTATUS DOKAN_CALLBACK MirrorCreateFile(LPCWSTR FileName, PDOKAN_IO_SECURITY_CONTEXT SecurityContext, ACCESS_MASK DesiredAccess, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PDOKAN_FILE_INFO DokanFileInfo) { WCHAR filePath[MAX_PATH]; HANDLE handle; DWORD fileAttr; NTSTATUS status = STATUS_SUCCESS; DWORD creationDisposition; DWORD fileAttributesAndFlags; DWORD error = 0; SECURITY_ATTRIBUTES securityAttrib; securityAttrib.nLength = sizeof(securityAttrib); securityAttrib.lpSecurityDescriptor = SecurityContext->AccessState.SecurityDescriptor; securityAttrib.bInheritHandle = FALSE; DokanMapKernelToUserCreateFileFlags( FileAttributes, CreateOptions, CreateDisposition, &fileAttributesAndFlags, &creationDisposition); GetFilePath(filePath, MAX_PATH, FileName); DbgPrint(L"CreateFile : %s\n", filePath); PrintUserName(DokanFileInfo); /* if (ShareMode == 0 && AccessMode & FILE_WRITE_DATA) ShareMode = FILE_SHARE_WRITE; else if (ShareMode == 0) ShareMode = FILE_SHARE_READ; */ DbgPrint(L"\tShareMode = 0x%x\n", ShareAccess); MirrorCheckFlag(ShareAccess, FILE_SHARE_READ); MirrorCheckFlag(ShareAccess, FILE_SHARE_WRITE); MirrorCheckFlag(ShareAccess, FILE_SHARE_DELETE); DbgPrint(L"\tAccessMode = 0x%x\n", DesiredAccess); MirrorCheckFlag(DesiredAccess, GENERIC_READ); MirrorCheckFlag(DesiredAccess, GENERIC_WRITE); MirrorCheckFlag(DesiredAccess, GENERIC_EXECUTE); MirrorCheckFlag(DesiredAccess, DELETE); MirrorCheckFlag(DesiredAccess, FILE_READ_DATA); MirrorCheckFlag(DesiredAccess, FILE_READ_ATTRIBUTES); MirrorCheckFlag(DesiredAccess, FILE_READ_EA); MirrorCheckFlag(DesiredAccess, READ_CONTROL); MirrorCheckFlag(DesiredAccess, FILE_WRITE_DATA); MirrorCheckFlag(DesiredAccess, FILE_WRITE_ATTRIBUTES); MirrorCheckFlag(DesiredAccess, FILE_WRITE_EA); MirrorCheckFlag(DesiredAccess, FILE_APPEND_DATA); MirrorCheckFlag(DesiredAccess, WRITE_DAC); MirrorCheckFlag(DesiredAccess, WRITE_OWNER); MirrorCheckFlag(DesiredAccess, SYNCHRONIZE); MirrorCheckFlag(DesiredAccess, FILE_EXECUTE); MirrorCheckFlag(DesiredAccess, STANDARD_RIGHTS_READ); MirrorCheckFlag(DesiredAccess, STANDARD_RIGHTS_WRITE); MirrorCheckFlag(DesiredAccess, STANDARD_RIGHTS_EXECUTE); // When filePath is a directory, needs to change the flag so that the file can // be opened. fileAttr = GetFileAttributes(filePath); if (fileAttr != INVALID_FILE_ATTRIBUTES && (fileAttr & FILE_ATTRIBUTE_DIRECTORY && DesiredAccess != DELETE)) { // Directory cannot be open for DELETE fileAttributesAndFlags |= FILE_FLAG_BACKUP_SEMANTICS; // AccessMode = 0; } DbgPrint(L"\tFlagsAndAttributes = 0x%x\n", fileAttributesAndFlags); MirrorCheckFlag(fileAttributesAndFlags, FILE_ATTRIBUTE_ARCHIVE); MirrorCheckFlag(fileAttributesAndFlags, FILE_ATTRIBUTE_ENCRYPTED); MirrorCheckFlag(fileAttributesAndFlags, FILE_ATTRIBUTE_HIDDEN); MirrorCheckFlag(fileAttributesAndFlags, FILE_ATTRIBUTE_NORMAL); MirrorCheckFlag(fileAttributesAndFlags, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); MirrorCheckFlag(fileAttributesAndFlags, FILE_ATTRIBUTE_OFFLINE); MirrorCheckFlag(fileAttributesAndFlags, FILE_ATTRIBUTE_READONLY); MirrorCheckFlag(fileAttributesAndFlags, FILE_ATTRIBUTE_SYSTEM); MirrorCheckFlag(fileAttributesAndFlags, FILE_ATTRIBUTE_TEMPORARY); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_WRITE_THROUGH); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_OVERLAPPED); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_NO_BUFFERING); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_RANDOM_ACCESS); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_SEQUENTIAL_SCAN); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_DELETE_ON_CLOSE); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_BACKUP_SEMANTICS); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_POSIX_SEMANTICS); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_OPEN_REPARSE_POINT); MirrorCheckFlag(fileAttributesAndFlags, FILE_FLAG_OPEN_NO_RECALL); MirrorCheckFlag(fileAttributesAndFlags, SECURITY_ANONYMOUS); MirrorCheckFlag(fileAttributesAndFlags, SECURITY_IDENTIFICATION); MirrorCheckFlag(fileAttributesAndFlags, SECURITY_IMPERSONATION); MirrorCheckFlag(fileAttributesAndFlags, SECURITY_DELEGATION); MirrorCheckFlag(fileAttributesAndFlags, SECURITY_CONTEXT_TRACKING); MirrorCheckFlag(fileAttributesAndFlags, SECURITY_EFFECTIVE_ONLY); MirrorCheckFlag(fileAttributesAndFlags, SECURITY_SQOS_PRESENT); if (creationDisposition == CREATE_NEW) { DbgPrint(L"\tCREATE_NEW\n"); } else if (creationDisposition == OPEN_ALWAYS) { DbgPrint(L"\tOPEN_ALWAYS\n"); } else if (creationDisposition == CREATE_ALWAYS) { DbgPrint(L"\tCREATE_ALWAYS\n"); } else if (creationDisposition == OPEN_EXISTING) { DbgPrint(L"\tOPEN_EXISTING\n"); } else if (creationDisposition == TRUNCATE_EXISTING) { DbgPrint(L"\tTRUNCATE_EXISTING\n"); } else { DbgPrint(L"\tUNKNOWN creationDisposition!\n"); } if ((CreateOptions & FILE_DIRECTORY_FILE) == FILE_DIRECTORY_FILE) { // It is a create directory request if (CreateDisposition == FILE_CREATE) { if (!CreateDirectory(filePath, &securityAttrib)) { error = GetLastError(); DbgPrint(L"\terror code = %d\n\n", error); status = ToNtStatus(error); } } else if (CreateDisposition == FILE_OPEN_IF) { if (!CreateDirectory(filePath, &securityAttrib)) { error = GetLastError(); if (error != ERROR_ALREADY_EXISTS) { DbgPrint(L"\terror code = %d\n\n", error); status = ToNtStatus(error); } } } if (status == STATUS_SUCCESS) { // FILE_FLAG_BACKUP_SEMANTICS is required for opening directory handles handle = CreateFileW(filePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, &securityAttrib, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (handle == INVALID_HANDLE_VALUE) { error = GetLastError(); DbgPrint(L"\terror code = %d\n\n", error); status = ToNtStatus(error); } else { DokanFileInfo->Context = (ULONG64)handle; // save the file handle in Context } } } else { // It is a create file request if (fileAttr != INVALID_FILE_ATTRIBUTES && (fileAttr & FILE_ATTRIBUTE_DIRECTORY)) { if (CreateDisposition == FILE_CREATE) { return STATUS_OBJECT_NAME_COLLISION; // File already exist because // GetFileAttributes found it } else { handle = CreateFileW(filePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, &securityAttrib, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } } else { handle = CreateFile( filePath, DesiredAccess, // GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, ShareAccess, &securityAttrib, // security attribute creationDisposition, fileAttributesAndFlags, // |FILE_FLAG_NO_BUFFERING, NULL); // template file handle } if (handle == INVALID_HANDLE_VALUE) { error = GetLastError(); DbgPrint(L"\terror code = %d\n\n", error); status = ToNtStatus(error); } else { DokanFileInfo->Context = (ULONG64)handle; // save the file handle in Context if (creationDisposition == OPEN_ALWAYS || creationDisposition == CREATE_ALWAYS) { error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { DbgPrint(L"\tOpen an already existing file\n"); SetLastError(ERROR_ALREADY_EXISTS); // Inform the driver that we have // open a already existing file return STATUS_SUCCESS; } } } } DbgPrint(L"\n"); return status; }
static NTSTATUS DOKAN_CALLBACK MirrorGetFileSecurity( LPCWSTR FileName, PSECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG BufferLength, PULONG LengthNeeded, PDOKAN_FILE_INFO DokanFileInfo) { WCHAR filePath[MAX_PATH]; UNREFERENCED_PARAMETER(DokanFileInfo); GetFilePath(filePath, MAX_PATH, FileName); DbgPrint(L"GetFileSecurity %s\n", filePath); MirrorCheckFlag(*SecurityInformation, FILE_SHARE_READ); MirrorCheckFlag(*SecurityInformation, OWNER_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, GROUP_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, DACL_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, SACL_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, LABEL_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, ATTRIBUTE_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, SCOPE_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, PROCESS_TRUST_LABEL_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, BACKUP_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, PROTECTED_DACL_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, PROTECTED_SACL_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, UNPROTECTED_DACL_SECURITY_INFORMATION); MirrorCheckFlag(*SecurityInformation, UNPROTECTED_SACL_SECURITY_INFORMATION); DbgPrint(L" Opening new handle with READ_CONTROL access\n"); HANDLE handle = CreateFile( filePath, READ_CONTROL | (((*SecurityInformation & SACL_SECURITY_INFORMATION) || (*SecurityInformation & BACKUP_SECURITY_INFORMATION)) ? ACCESS_SYSTEM_SECURITY : 0), FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, // security attribute OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, // |FILE_FLAG_NO_BUFFERING, NULL); if (!handle || handle == INVALID_HANDLE_VALUE) { DbgPrint(L"\tinvalid handle\n\n"); int error = GetLastError(); return ToNtStatus(error); } if (!GetUserObjectSecurity(handle, SecurityInformation, SecurityDescriptor, BufferLength, LengthNeeded)) { int error = GetLastError(); if (error == ERROR_INSUFFICIENT_BUFFER) { DbgPrint(L" GetUserObjectSecurity failed: ERROR_INSUFFICIENT_BUFFER\n"); CloseHandle(handle); return STATUS_BUFFER_OVERFLOW; } else { DbgPrint(L" GetUserObjectSecurity failed: %d\n", error); CloseHandle(handle); return ToNtStatus(error); } } CloseHandle(handle); return STATUS_SUCCESS; }
static NTSTATUS DOKAN_CALLBACK MirrorReadFile( LPCWSTR FileName, LPVOID Buffer, DWORD BufferLength, LPDWORD ReadLength, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo) { WCHAR filePath[MAX_PATH]; HANDLE handle = (HANDLE)DokanFileInfo->Context; ULONG offset = (ULONG)Offset; BOOL opened = FALSE; GetFilePath(filePath, MAX_PATH, FileName); DbgPrint(L"ReadFile : %s\n", filePath); if (!handle || handle == INVALID_HANDLE_VALUE) { DbgPrint(L"\tinvalid handle, cleanuped?\n"); handle = CreateFile( filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); DbgPrint(L"\tCreateFile error : %d\n\n", error); return ToNtStatus(error); } opened = TRUE; } LARGE_INTEGER distanceToMove; distanceToMove.QuadPart = Offset; if (!SetFilePointerEx(handle, distanceToMove, NULL, FILE_BEGIN)) { DWORD error = GetLastError(); DbgPrint(L"\tseek error, offset = %d\n\n", offset); if (opened) CloseHandle(handle); return ToNtStatus(error); } if (!ReadFile(handle, Buffer, BufferLength, ReadLength,NULL)) { DWORD error = GetLastError(); DbgPrint(L"\tread error = %u, buffer length = %d, read length = %d\n\n", error, BufferLength, *ReadLength); if (opened) CloseHandle(handle); return ToNtStatus(error); } else { DbgPrint(L"\tread %d, offset %d\n\n", *ReadLength, offset); } if (opened) CloseHandle(handle); return STATUS_SUCCESS; }