Сообщение формата API Win32 с node-ffi

Я пытаюсь использовать node-ffi для взаимодействия с Win32 API FormatMessageA, однако я не могу получить параметр out lpBuffer, вот фрагмент кода, чтобы показать, что я пробовал

   'use strict';

   const ref = require('ref');
   const ffi = require('ffi');

   const Kernel32 = ffi.Library('Kernel32.dll', {
       FormatMessageA: ['ulong', [
           'ulong', //flags 
           'void *', 
           'ulong', //status number
           'ulong', //language 
           'uchar *',
           'ulong',
           'void *'
       ]]
   });


   const FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;
   const FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100;
   const FORMAT_MESSAGE_IGNORE_INSERTS = 0x200;

   const lpBuffer = ref.alloc('uchar *'); 

   const result = Kernel32.FormatMessageA(
       FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
       null, 
       0x80090300, //error code
       0,
       lpBuffer,
       0, 
       null
   );

   console.log(result); //prints 57 bytes

Я знаю, что функция выполнена успешно, поскольку она возвращает 57, однако я не могу получить значение lpBuffer, содержащее требуемую строку ошибки.


person simon-p-r    schedule 23.03.2017    source источник
comment
Из MSDN: функция FormatMessage: Параметр lpBuffer является указателем на LPTSTR; вы должны привести указатель к LPTSTR (например, (LPTSTR)&lpBuffer). Второй пример (в конце той же страницы) иллюстрирует, как использовать FORMAT_MESSAGE_ALLOCATE_BUFFER .   -  person CristiFati    schedule 24.03.2017
comment
Это использует javascript с использованием ffi для создания типа данных? Я могу сделать это в c без проблем, только не через сторонний интерфейс   -  person simon-p-r    schedule 24.03.2017
comment
Да, я знаю, что пример предназначен для C, а вы используете JS (о котором я совершенно ничего не знаю), но (при условии, что ваш код правильный), документация говорит мне, что lpBuffer должно быть ref.alloc('uchar **') (не знаю, имеет ли это смысл в JS).   -  person CristiFati    schedule 24.03.2017
comment
Да бывает, не видел. Я проверю, и если вы хотите дать ответ, я соглашусь, если он сработает.   -  person simon-p-r    schedule 24.03.2017
comment
Это сработало очарование, большое спасибо! Если вы напишете ответ, я с радостью его приму!   -  person simon-p-r    schedule 24.03.2017


Ответы (1)


Как я указал в своем st комментарии, согласно [MSDN] FormatMessage функция:

  • FORMAT_MESSAGE_ALLOCATE_BUFFER описание:
    #P2#
  • Пример (2nd) внизу страницы:

    // Some code (not relevant for this problem)
    LPWSTR pBuffer = NULL;
    // Some more code (still not relevant)
    FormatMessage(FORMAT_MESSAGE_FROM_STRING |
                  FORMAT_MESSAGE_ALLOCATE_BUFFER,
                  pMessage, 
                  0,
                  0,
                  (LPWSTR)&pBuffer,
    // The rest of the code (not relevant)
    

когда аргумент dwFlags состоит из FORMAT_MESSAGE_ALLOCATE_BUFFER, функция ожидает, что аргумент lpBuffer, который является LPTSTR (указатель на TCHAR), на самом деле будет указателем на LPTSTR (двойной указатель на TCHAR) приведение изменено на LPTSTR.

Это, переведенное на JS (в котором у меня нет опыта), будет означать:

const lpBuffer = ref.alloc('uchar **');

Примечание: согласно той же странице, буфер должен быть освобожден с помощью LocalFree, когда он больше не нужен (имеет смысл, так как FormatMessage выделяет для него память - поэтому он должен быть двойным указателем). Опять же, не знаю, как это отразится в JS (что я знаю, так это то, что LocalFree следует вызывать в uchar *(разыменованном) буфере, а не непосредственно в lpBuffer).

person CristiFati    schedule 24.03.2017
comment
Да, мне пришлось написать интерфейс javascript для GetProcessHeap и HeapFree, чтобы я мог освободить буфер от javascript, чтобы предотвратить утечку памяти. - person simon-p-r; 25.03.2017