WinAPI -> MQL5 x64

 

РЕШЕНО:

 


Хочу вызвать из MQL5 WinAPI функцию создания папки CreateDirectory (вызывать буду CreateDirectoryW). Widows 10, x64.

Итак:

BOOL WINAPI CreateDirectory(
  _In_     LPCTSTR               lpPathName,
  _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
);

Parameters

lpPathName [in]

The path of the directory to be created.

 
lpSecurityAttributes [in, optional]

A pointer to a SECURITY_ATTRIBUTES structure. The lpSecurityDescriptor member of the structure specifies a security descriptor for the new directory. If lpSecurityAttributes is NULL, the directory gets a default security descriptor. The ACLs in the default security descriptor for a directory are inherited from its parent directory.

LPCTSTR               lpPathName - переменная (не массив) string

LPSECURITY_ATTRIBUTES lpSecurityAttributes - указатель? ссылка? на структуру.


Пока даже структуру не расписываю, банально не понимаю как скрестить ежа и удава. Пока так:

//+------------------------------------------------------------------+
//|                                                       WinAPI.mqh |
//|                              Copyright © 2016, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2016, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.000"

//+------------------------------------------------------------------+
//| SECURITY_ATTRIBUTES structure                                    |
//+------------------------------------------------------------------+
struct SECURITY_ATTRIBUTES
  {
   uint              nLength;
   uint             &lpSecurityDescriptor;
   bool              bInheritHandle;
  };

#import "kernel32.dll"
int      GetLastError();
bool     CreateDirectoryW(string lpPathName,SECURITY_ATTRIBUTES &lpSecurityAttributes);

#import


Что делаю неправильно?

CreateDirectory function (Windows)
  • msdn.microsoft.com
Creates a new directory. If the underlying file system supports security on files and directories, the function applies a specified security descriptor to the new directory. Syntax Parameters lpPathName [in] The path of the directory to be created. For the ANSI version of this function, there is a default string size limit for paths of 248...
Файлы:
WinAPI.mqh  3 kb
 
Vladimir Karputov:

Хочу вызвать из MQL5 WinAPI функцию создания папки CreateDirectory (вызывать буду CreateDirectoryW). Widows 10, x64.

Итак:

Parameters

lpPathName [in]

The path of the directory to be created.

 
lpSecurityAttributes [in, optional]

A pointer to a SECURITY_ATTRIBUTES structure. The lpSecurityDescriptor member of the structure specifies a security descriptor for the new directory. If lpSecurityAttributes is NULL, the directory gets a default security descriptor. The ACLs in the default security descriptor for a directory are inherited from its parent directory.

LPCTSTR               lpPathName - переменная (не массив) string

LPSECURITY_ATTRIBUTES lpSecurityAttributes - указатель? ссылка? на структуру.


Пока даже структуру не расписываю, банально не понимаю как скрестить ежа и удава. Пока так:


Что делаю неправильно?

так а что не получается-то? и на win64 указатели 64-битные, не int

все, что lp*******, это long pointer, но на деле 32 бит, ибо унаследовалось из 16-разрядной виндовс 3.1, где указатели были 16 бит

 
Alexey Volchanskiy:

так а что не получается-то? и на win64 указатели 64-битные, не int

Не получается ничего. Вообще не вижу как скрещивать ежа и удава. 

Например структура SECURITY_ATTRIBUTES - я чувствую, что нахомутал в ней.

 
Vladimir Karputov:

Не получается ничего. Вообще не вижу как скрещивать ежа и удава. 

Например структура SECURITY_ATTRIBUTES - я чувствую, что нахомутал в ней.

Вроде ( по памяти) можно NULL задавать, если секретность не нужна

 

Работает!

//+------------------------------------------------------------------+
//|                                                       WinAPI.mq5 |
//|                              Copyright © 2018, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2018, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.001"
#property script_show_inputs
//--- input parameters
string   PathName   ="C:\\Users\\barab\\Desktop\\Mql5";      // PathName

#import "kernel32.dll"
int      GetLastError();
bool     CreateDirectoryW(string lpPathName,long null);

#import

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   if(!CreateDirectoryW(PathName,0))
      PrintFormat("Failed CreateDirectoryW (%s) with error: %d",PathName,kernel32::GetLastError());
  }
//+------------------------------------------------------------------+


Теперь другой вопрос: как засунуть во входной параметр переменную среды %USERNAME% ? Вариант

string   PathName   ="C:\\Users\\%USERNAME%\\Desktop\\Mql5";      // PathName

не проходит

Файлы:
WinAPI.mq5  3 kb
 
Vladimir Karputov:

Работает!


Теперь другой вопрос: как засунуть во входной параметр переменную среды %USERNAME% ? Вариант

не проходит

я так понимаю, это нужно

https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx

GetEnvironmentVariable function (Windows)
  • msdn.microsoft.com
Retrieves the contents of the specified variable from the environment block of the calling process. Syntax Parameters lpName [in, optional] The name of the environment variable. lpBuffer [out, optional] A pointer to a buffer that receives the contents of the specified environment variable as a null-terminated string. An environment variable has...
 
Alexey Volchanskiy:

я так понимаю, это нужно

https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx

Я уже понял, что MQL5 не поддерживает переменные среды. Нужно через WinAPI/

 
Vladimir Karputov:

Я уже понял, что MQL5 не поддерживает переменные среды. Нужно через WinAPI/

ну попробуй через АПИ, я по другому и не пробовал

 

Раскурить код:

TCHAR szPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, szPath)))
{
    //....
}

спортировать его на MQL, дальше легко

 
Vladimir Karputov:

Работает!


Теперь другой вопрос: как засунуть во входной параметр переменную среды %USERNAME% ? Вариант

не проходит

Здесь подсказали, что при вызове dll из MQL5 вместо string переменной нужно передавать массив char.

Но если делаю так:

//+------------------------------------------------------------------+
//|                                                       WinAPI.mq5 |
//|                              Copyright © 2018, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2018, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.002"
#property script_show_inputs
//--- input parameters
string   PathName="C:\\Users\\barab\\Desktop\\Mql5";      // PathName

#import "kernel32.dll"
int      GetLastError();
bool     CreateDirectoryW(char  &lpPathName[],long null);

#import
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   char arr_path[];
   StringToCharArray(PathName,arr_path);

   if(!CreateDirectoryW(arr_path,0))
      PrintFormat("Failed CreateDirectoryW (\"%s\") with error: %x",PathName,kernel32::GetLastError());
  }
//+------------------------------------------------------------------+

получаю ошибку

2018.05.29 07:46:47.300 WinAPI (GBPUSD,H1)      Failed CreateDirectoryW ("C:\Users\barab\Desktop\Mql5") with error: 5
ERROR_ACCESS_DENIED5 (0x5)

Access is denied.

Файлы:
WinAPI.mq5  3 kb
 
Vladimir Karputov:

Здесь подсказали, что при вызове dll из MQL5 вместо string переменной нужно передавать массив char.

Но если делаю так:

получаю ошибку

ERROR_ACCESS_DENIED5 (0x5)

Access is denied.

Из описания  CreateDirectory следует, что второй параметр (опциональный) нужно передавать как NULL (не MQL5 NULL, а c++ NULL)

lpSecurityAttributes [in, optional]

A pointer to a SECURITY_ATTRIBUTES structure. The lpSecurityDescriptor member of the structure specifies a security descriptor for the new directory. If lpSecurityAttributes is NULL, the directory gets a default security descriptor. The ACLs in the default security descriptor for a directory are inherited from its parent directory.


Значит задача сводится к тому, как и что объявить в 

#import "kernel32.dll"
int      GetLastError();
bool     CreateDirectoryW(char  &lpPathName[],long &null);
#import

чтобы это соответствовало c++ NULL.

CreateDirectory function (Windows)
  • msdn.microsoft.com
Creates a new directory. If the underlying file system supports security on files and directories, the function applies a specified security descriptor to the new directory. Syntax Parameters lpPathName [in] The path of the directory to be created. For the ANSI version of this function, there is a default string size limit for paths of 248...
Причина обращения: