diff options
| author | George Hazan <george.hazan@gmail.com> | 2023-05-30 20:38:02 +0300 | 
|---|---|---|
| committer | George Hazan <george.hazan@gmail.com> | 2023-05-30 20:38:07 +0300 | 
| commit | 18b2640d91af23ee1cd03f8aadbb52137298e53d (patch) | |
| tree | 61385b3b681ed54e30fb5676d8f76e49580c0566 /protocols/Telegram/tdlib/td/tdutils | |
| parent | 9154bda3c04a2c78340a6a7a4684814fc640a2f4 (diff) | |
fixes #3309 (Telegram: crash under WinXP)
Diffstat (limited to 'protocols/Telegram/tdlib/td/tdutils')
| -rw-r--r-- | protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp | 192 | 
1 files changed, 180 insertions, 12 deletions
diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp index 4297e9f368..aabcb0156c 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp @@ -42,14 +42,61 @@  #endif  #if TD_PORT_WINDOWS +#define STATUS_INVALID_INFO_CLASS  0xC0000003L + +typedef enum _FILE_INFORMATION_CLASS +{ +   FileDirectoryInformation = 1, +   FileFullDirectoryInformation, +   FileBothDirectoryInformation, +   FileBasicInformation, +   FileStandardInformation, +   FileInternalInformation, +   FileEaInformation, +   FileAccessInformation, +   FileNameInformation, +   FileRenameInformation, +   FileLinkInformation, +   FileNamesInformation, +   FileDispositionInformation, +   FilePositionInformation, +   FileFullEaInformation, +   FileModeInformation, +   FileAlignmentInformation, +   FileAllInformation, +   FileAllocationInformation, +   FileEndOfFileInformation, +   FileAlternateNameInformation, +   FileStreamInformation, +   FilePipeInformation, +   FilePipeLocalInformation, +   FilePipeRemoteInformation, +   FileMailslotQueryInformation, +   FileMailslotSetInformation, +   FileCompressionInformation, +   FileCopyOnWriteInformation, +   FileCompletionInformation, +   FileMoveClusterInformation, +   FileQuotaInformation, +   FileReparsePointInformation, +   FileNetworkOpenInformation, +   FileObjectIdInformation, +   FileTrackingInformation, +   FileOleDirectoryInformation, +   FileContentIndexInformation, +   FileInheritContentIndexInformation, +   FileOleInformation, +   FileMaximumInformation +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; + +  #ifdef WIN32_LEAN_AND_MEAN  #include <winioctl.h>  #endif // WIN32_LEAN_AND_MEAN  typedef struct _IO_STATUS_BLOCK  { -   union -   { +   union {        NTSTATUS Status;        PVOID Pointer;     } DUMMYUNIONNAME; @@ -57,8 +104,134 @@ typedef struct _IO_STATUS_BLOCK     ULONG_PTR Information;  } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; -typedef NTSTATUS (WINAPI *pfnNtQueryInformationFile)(HANDLE handle, IO_STATUS_BLOCK *io, void *ptr, ULONG len, int class_); -static pfnNtQueryInformationFile fnNtQueryInformationFile = 0; +typedef NTSTATUS (CALLBACK *pfnNtQueryDirectoryFile)( +   HANDLE                 FileHandle, +   HANDLE                 Event, +   PVOID                  ApcRoutine, +   PVOID                  ApcContext, +   PIO_STATUS_BLOCK       IoStatusBlock, +   PVOID                  FileInformation, +   ULONG                  Length, +   FILE_INFORMATION_CLASS FileInformationClass, +   BOOLEAN                ReturnSingleEntry, +   WCHAR*                 FileName, +   BOOLEAN                RestartScan); + +static pfnNtQueryDirectoryFile fnNtQueryDirectoryFile = nullptr; + +typedef NTSTATUS (CALLBACK *pfnNtQueryInformationFile)( +   HANDLE                 FileHandle, +   PIO_STATUS_BLOCK       IoStatusBlock, +   PVOID                  FileInformation, +   ULONG                  Length, +   FILE_INFORMATION_CLASS FileInformationClass); + +static pfnNtQueryInformationFile fnNtQueryInformationFile = nullptr; + +static BOOL bNtdllInited = false; + +static BOOL WINAPI GetFileInformationByHandleExStub( +   _In_  HANDLE hFile, +   _In_  FILE_INFO_BY_HANDLE_CLASS FileInformationClass, +   _Out_writes_bytes_(dwBufferSize) LPVOID lpFileInformation, +   _In_  DWORD dwBufferSize) +{ +   FILE_INFORMATION_CLASS NtFileInformationClass; +   DWORD cbMinBufferSize; +   BOOLEAN RestartScan = false; + +   switch (FileInformationClass) // Purosham Sahanu InformationClass  +   { +   case FileBasicInfo: +      NtFileInformationClass = FileBasicInformation; +      cbMinBufferSize = sizeof(FILE_BASIC_INFO); +      break; +   case FileStandardInfo: +      NtFileInformationClass = FileStandardInformation; +      cbMinBufferSize = sizeof(FILE_STANDARD_INFO); +      break; +   case FileNameInfo: +      NtFileInformationClass = FileNameInformation; +      cbMinBufferSize = sizeof(FILE_NAME_INFO); +      break; +   case FileStreamInfo: +      NtFileInformationClass = FileStreamInformation; +      cbMinBufferSize = sizeof(FILE_STREAM_INFO); +      break; +   case FileCompressionInfo: +      NtFileInformationClass = FileCompressionInformation; +      cbMinBufferSize = sizeof(FILE_COMPRESSION_INFO); +      break; +   default: +      SetLastError(ERROR_INVALID_PARAMETER); +      return FALSE; +      break; +   } + +   if (cbMinBufferSize > dwBufferSize) { +      SetLastError(ERROR_BAD_LENGTH); +      return FALSE; +   } + +   if (!bNtdllInited) { +      bNtdllInited = true; + +      HINSTANCE hdll = LoadLibraryA("ntdll.dll"); +      fnNtQueryDirectoryFile = (pfnNtQueryDirectoryFile)GetProcAddress(hdll, "NtQueryDirectoryFile"); +      fnNtQueryInformationFile = (pfnNtQueryInformationFile)GetProcAddress(hdll, "NtQueryInformationFile"); +   } + +   int Status = ERROR_SUCCESS; +   IO_STATUS_BLOCK IoStatusBlock; +   if (fnNtQueryDirectoryFile) { +      Status = fnNtQueryDirectoryFile( +         hFile, +         nullptr, +         nullptr, +         nullptr, +         &IoStatusBlock, +         lpFileInformation, +         dwBufferSize, +         NtFileInformationClass, +         false, +         nullptr, +         RestartScan +      ); + +      if (STATUS_PENDING == Status) { +         if (WaitForSingleObjectEx(hFile, 0, FALSE) == WAIT_FAILED) { +            return FALSE; +         } + +         Status = IoStatusBlock.Status; +      } +      else if (Status == STATUS_INVALID_INFO_CLASS) +         goto LBL_CheckFile; +   } +   else { +LBL_CheckFile: +      if (!fnNtQueryInformationFile) { +         SetLastError(ERROR_INVALID_FUNCTION); +         return FALSE; +      } + +      Status = fnNtQueryInformationFile(hFile, &IoStatusBlock, lpFileInformation, dwBufferSize, NtFileInformationClass); +   } + +   if (Status >= ERROR_SUCCESS) { +      if (FileStreamInfo == FileInformationClass && IoStatusBlock.Information == 0) { +         SetLastError(ERROR_HANDLE_EOF); +         return FALSE; +      } +      else { +         return TRUE; +      } +   } +   else { +      SetLastError(Status); +      return FALSE; +   } +}  #endif @@ -549,10 +722,7 @@ struct FileSize {  Result<FileSize> get_file_size(const FileFd &file_fd) {    FILE_STANDARD_INFO standard_info; -  IO_STATUS_BLOCK io = {}; -  if (fnNtQueryInformationFile == nullptr) -     fnNtQueryInformationFile = (pfnNtQueryInformationFile)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationFile"); -  if (fnNtQueryInformationFile(file_fd.get_native_fd().fd(), &io, &standard_info, sizeof(standard_info), 5)) { +  if (!GetFileInformationByHandleExStub(file_fd.get_native_fd().fd(), FileStandardInfo, &standard_info, sizeof(standard_info))) {      return OS_ERROR("Get FileStandardInfo failed");    } @@ -597,10 +767,8 @@ Result<Stat> FileFd::stat() const {    Stat res;    FILE_BASIC_INFO basic_info; -  IO_STATUS_BLOCK io = {}; -  if (fnNtQueryInformationFile == nullptr) -     fnNtQueryInformationFile = (pfnNtQueryInformationFile)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationFile"); -  if (fnNtQueryInformationFile(get_native_fd().fd(), &io, &basic_info, sizeof(basic_info), 4)) { +  auto status = GetFileInformationByHandleExStub(get_native_fd().fd(), FileBasicInfo, &basic_info, sizeof(basic_info)); +  if (!status) {       return OS_ERROR("Get FileStandardInfo failed");    }  | 
