Нужна помощь профиков WinAPI и x64

 

Вобщем портирую (давно и безуспешно) некоторый код который нормально пашет под x86 терминалом.

Ни дебажить, ни определить где глюка не представляется возможным. Возможно просто ошибка фундаментальная и я чего-то не догоняю\не замечаю\не понимаю.

Кто разбирается в теме, пожалуйста, просмотрите на предмет ляпов, неправильного подхода, наставьте на путь истинный.

Вот такой импорт:

#import "kernel32.dll"
   int   DeleteFileW (string lpFileName);
   
   int   CloseHandle(int hObject);
   int   CloseHandle(long hObject);
   
   int   CreateFileW(      string lpFileName,         int dwDesiredAccess, 
                           int dwShareMode,           int lpSecurityAttributes,
                           int dwCreationDisposition, int dwFlagsAndAttributes, 
                           int hTemplateFile
                     );
   long  CreateFileW(      string lpFileName,         int dwDesiredAccess, 
                           int dwShareMode,           long lpSecurityAttributes,
                           int dwCreationDisposition, int dwFlagsAndAttributes, 
                           long hTemplateFile
                     );

   int   SetFilePointer(int hFile, int lDistanceToMove, int& lpDistanceToMoveHigh[], int dwMoveMethod);
   int   SetFilePointer(long hFile, int lDistanceToMove, int& lpDistanceToMoveHigh[], int dwMoveMethod);
   
   int   SetEndOfFile (int hFile);
   int   SetEndOfFile (long hFile);
   
   int   ReadFile(int hFile, ushort& lpBuffer[], int nNumberOfBytesToRead, int& lpNumberOfBytesRead[], int lpOverlapped);
   int   ReadFile(long hFile, ushort& lpBuffer[], int nNumberOfBytesToRead, int& lpNumberOfBytesRead[], long lpOverlapped);

   int   WriteFile(int  hFile, int& lpBuffer[], int nNumberOfBytesToWrite, int& lpNumberOfBytesWritten[], int lpOverlapped);
   int   WriteFile(long hFile, int& lpBuffer[], int nNumberOfBytesToWrite, int& lpNumberOfBytesWritten[], long lpOverlapped);

   int   GetFileSize(int hFile,  int notUsed = 0);
   int   GetFileSize(long hFile,  long notUsed = 0);
   
   long  FindFirstFileW(string path, int& answer[]);

   int   FindNextFileW(int handle, int& answer[]);
   int   FindNextFileW(long handle, int& answer[]);

   int   FindClose(int handle);
   int   FindClose(long handle);
   
   int   CreateDirectoryW(string path, int securityAttributes /*set to 0*/);
   int   CreateDirectoryW(string path, long securityAttributes /*set to 0*/);
   
#import

Вот функции которые не дружат с терминалом (причем в дебаге и не в дебаге падает в разных местах)

int GetFileList(string path, string filter, string& list[])
{
   int Win32Data[80];
   ArrayInitialize(Win32Data, 0);

   RtlSetLastWin32Error(0);
   long hFind = FindFirstFileW(path + filter, Win32Data);
   
   if (INVALID_HANDLE_VALUE == hFind)
   {
      return (RtlGetLastWin32Error());
   }
   
   ArrayResize(list, 0);
   
   if ((Win32Data[0] & FILE_ATTRIBUTE_DIRECTORY) == 0) // if found item is file, not directory
   {
      ArrayResize(list, 1);
      list[0] = StringFromBuffer(Win32Data);
   }
   ArrayInitialize(Win32Data, 0);
   
   int nextFound = _IsX64 ? FindNextFileW(hFind, Win32Data) : FindNextFileW((int)hFind, Win32Data);
   while (nextFound != 0)
   {
      if ((Win32Data[0] & FILE_ATTRIBUTE_DIRECTORY) == 0) // if found item is file, not directory
      {
         int size = ArraySize(list);
         ArrayResize(list, size + 1);
         list[size] = StringFromBuffer(Win32Data);
      }
      ArrayInitialize(Win32Data, 0);
      nextFound = _IsX64 ? FindNextFileW(hFind, Win32Data) : FindNextFileW((int)hFind, Win32Data);
   }
   
   if (_IsX64) FindClose(hFind);
   else        FindClose((int)hFind);
   
   return (0);
}

long TryToCaptureFile(string fileName, int& err)
{
   RtlSetLastWin32Error(0);
   long hFile;
   if (_IsX64) hFile = CreateFileW(fileName, F_GENERIC_WRITE | F_GENERIC_READ, F_FILE_SHARE_NO, (long)0, F_OPEN_ALWAYS, 0, (long)0);
   else        hFile = CreateFileW(fileName, F_GENERIC_WRITE | F_GENERIC_READ, F_FILE_SHARE_NO, 0, F_OPEN_ALWAYS, 0, 0);
   
   err = RtlGetLastWin32Error();
   return (hFile);
}

int ReadFileToString(string fileName, string& data)
{
   int result = 0;
   RtlSetLastWin32Error(0);
   long hFile;
   if (_IsX64) hFile = CreateFileW(fileName, F_GENERIC_READ, F_FILE_SHARE_READ, (long)0, F_OPEN_EXISTING, 0, (long)0);
   else        hFile = CreateFileW(fileName, F_GENERIC_READ, F_FILE_SHARE_READ, 0, F_OPEN_EXISTING, 0, 0);
   
   int err = RtlGetLastWin32Error();
   
   if (INVALID_HANDLE_VALUE == hFile)
   {
      return (err);
   }
   
   RtlSetLastWin32Error(0);
   uint size;
   if (_IsX64) size = GetFileSize(hFile, (long)0);
   else        size = GetFileSize((int)hFile, (int)0);
   
   if (size == INVALID_FILE_SIZE)
   {
      result = RtlGetLastWin32Error();
   }
   else
   {
      ushort buffer[];
      ArrayResize(buffer, size/2); // 4 == sizeof(int) / sizeof(ushort)
      
      int read[] = {0};
      
      RtlSetLastWin32Error(0);
      int readRes;
      if (_IsX64) readRes = ReadFile(hFile, buffer, size, read, (long)0);
      else        readRes = ReadFile((int)hFile, buffer, size, read, 0);
      if (readRes != 0)
      {
         // we have read the file. need to convert it to string
         string contents;
         contents = "";
         
         for (uint i = 0; i < size/2; i++)
         {
            StringSetCharacter(contents, i, buffer[i]);
         }
         
         data = contents;
      }
      else
      {
         result = RtlGetLastWin32Error();
      }
   }
   
   if (_IsX64) CloseHandle(hFile);
   else        CloseHandle((int)hFile);
   return (result);
}
 
TheXpert:

Вобщем портирую (давно и безуспешно) некоторый код который нормально пашет под x86 терминалом.

Ни дебажить, ни определить где глюка не представляется возможным. Возможно просто ошибка фундаментальная и я чего-то не догоняю\не замечаю\не понимаю.

Кто разбирается в теме, пожалуйста, просмотрите на предмет ляпов, неправильного подхода, наставьте на путь истинный.

Вот такой импорт:

Вот функции которые не дружат с терминалом (причем в дебаге и не в дебаге падает в разных местах)

может для полной однозначности вот таким манером все сделать при импорте:

 

#import "kernel32.dll"
   int   DeleteFileW (string lpFileName);
   
   
   if (_IsX64) int   CloseHandle(long hObject);
   else        int   CloseHandle(int hObject);
...
...
...

 

Что-то посмотрел в справке MQL5, не нашел там _IsX64. Есть стандартная функия TerminalInfoInteger. Может этот _IsX64 нечто недокументированное и иногда не работает?

if(true == (bool)TerminalInfoInteger(TERMINAL_X64))
   size = GetFileSize(hFile, (long)0);
else
   size = GetFileSize((int)hFile, (int)0);
   
 
Еще вопрос -- а нету ли дефайна для разделения x64 и x86? На самом деле очень неудобно во время исполнения делать то что можно было отсеять во время компиляции.
 

У Вас в коде всё нормально, неправильно только размер массива Win32Data.

Должно быть так:

int Win32Data[148];

А ещё лучше определить структуру.

#define MAX_PATH 260

struct FILETIME
{
   DWORD dwLowDateTime;
   DWORD dwHighDateTime;
};

struct WIN32_FIND_DATA
{
   DWORD dwFileAttributes;
   FILETIME ftCreationTime;
   FILETIME ftLastAccessTime;
   FILETIME ftLastWriteTime;
   DWORD nFileSizeHigh;
   DWORD nFileSizeLow;
   DWORD dwReserved0;
   DWORD dwReserved1;
   WCHAR cFileName[ MAX_PATH ];
   WCHAR cAlternateFileName[ 14 ];
};
Дефайна нет и не будет. Я уже просил в сервисдеске.
Я его определяю сам.
#define _WIN64  // Только для 64-разрядного терминала!

В этом даже есть свой плюс: можно в одном терминале компилировать и для 32 и для 64 разрядного терминала.
После этого вставляю такие определения:

#ifdef _WIN64
#define PVOID ulong
#else
#define PVOID uint
#endif

#define HANDLE PVOID
#define HWND PVOID

#define BOOL int
#define FALSE 0
#define TRUE  1

#define BYTE uchar
#define WORD ushort
#define DWORD uint
#define UINT uint

#define CHAR char
#define WCHAR ushort

Тогда объявления функций будут такие:

#import "kernel32.dll"
   BOOL DeleteFileW( string lpFileName );
   BOOL CloseHandle( HANDLE hObject );
   HANDLE CreateFileW( string lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, PVOID lpSecurityAttributes,
                  DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, PVOID hTemplateFile );
   DWORD SetFilePointer( HANDLE hFile, int lDistanceToMove, int& lpDistanceToMoveHigh, uint dwMoveMethod );
   BOOL SetEndOfFile( HANDLE hFile );
   BOOL ReadFile( HANDLE hFile, ushort& lpBuffer[], uint nNumberOfBytesToRead, uint& lpNumberOfBytesRead, PVOID lpOverlapped );
   BOOL WriteFile( HANDLE hFile, int& lpBuffer[], uint nNumberOfBytesToWrite, uint& lpNumberOfBytesWritten, PVOID lpOverlapped );
   DWORD GetFileSize( HANDLE hFile, PVOID lpFileSizeHigh );
   HANDLE FindFirstFileW( string path, WIN32_FIND_DATA& lpFindFileData );
   BOOL FindNextFileW( HANDLE hFindFile, WIN32_FIND_DATA& lpFindFileData );
   BOOL FindClose( HANDLE hFindFile );
   BOOL CreateDirectoryW( string path, PVOID securityAttributes );
#import
 

Да вроде правильный размер... должен быть 320 байт 80*4 как раз

____________

Ан нет, ваша правда, 592 байта. 320 байт было для не юникода.

 
Не дождешся - обстегают и ничего путнего не  предложат.....
 
Zloy_Koldun:
Спасибо! Это был именно тот затык из-за которого все не пахало!
Причина обращения: