summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2023-05-30 20:38:02 +0300
committerGeorge Hazan <george.hazan@gmail.com>2023-05-30 20:38:07 +0300
commit18b2640d91af23ee1cd03f8aadbb52137298e53d (patch)
tree61385b3b681ed54e30fb5676d8f76e49580c0566 /protocols
parent9154bda3c04a2c78340a6a7a4684814fc640a2f4 (diff)
fixes #3309 (Telegram: crash under WinXP)
Diffstat (limited to 'protocols')
-rw-r--r--protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp192
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");
}