windows 如何用ffi和ref-struct读取16位整数

enyaitl3  于 2023-03-13  发布在  Windows
关注(0)|答案(1)|浏览(130)

我能够使用一些基本的Win32 C/C++代码加载某个DLL并调用该DLL中的某个函数。
我调用的函数需要调用者分配的缓冲区的地址,调用者将在给定的偏移量处用16位整数填充该地址。
使用一个调试器和一个断点,我可以看到调用后的内存,在给定的偏移量,16位整数是可以的:低位优先,所以LSB优先。
现在,我想从nodejs呼叫

const ffi = require('ffi-napi');
const ref = require('ref-napi');
const StructType = require('ref-struct-napi');
const ArrayType = require('ref-array-napi');

const hllapi = ffi.Library('WHLAPI32', {
  'WinHLLAPI': [ref.types.void, [ref.refType(ref.types.uint16),
                                 ref.refType(ref.types.void),
                                 ref.refType(ref.types.uint16),
                                 ref.refType(ref.types.uint16)]]
});

var QuerySessionStatusStruct = StructType({
    ShortName: ref.types.uchar,         //  1
    LongName: ArrayType('uchar', 8),    //  9
    Type: ref.types.uchar,              // 10
    Characteristics: ref.types.uchar,   // 11
    Rows: ref.types.uint16,             // 13
    Cols: ref.types.uint16,             // 15
    CodePage: ref.types.uint16,         // 17
    Reserved: ref.types.uchar           // 18
 });
 

const function_number = ref.alloc(ref.types.uint16, 22);
const QuerySessionStatusStructInstance = new QuerySessionStatusStruct;
QuerySessionStatusStructInstance.ShortName='B';
const length = ref.alloc(ref.types.uint16, 18);
const ps_position = ref.alloc(ref.types.uint16, 0);

hllapi.WinHLLAPI(function_number, QuerySessionStatusStructInstance.ref(), length, ps_position );

console.log( "RC is: " + ps_position.deref());
console.log( 'Long Name is: '+String.fromCharCode.apply(null, QuerySessionStatusStructInstance.LongName));
console.log( 'Rows is: '+QuerySessionStatusStructInstance.Rows);

结果:

RC is: 0
Long Name is: MAINFRAM
Rows is: 20480

行数应该是24!(在C中我可以看到0x 18 - 0x 00)20480是0x 5000...我做错了什么?
编辑:当我在C
中看到正确的LSB时,我有了一个奇怪的想法,将结构的声明从:

Rows: ref.types.uint16,             // 13

致:

Rows: ref.types.uchar,              // 12
Padding: ref.types.uchar,           // 13

现在我有了正确的输出:

RC is: 0
Long Name is: MAINFRAM
Rows is: 24

但是如果uchar是0x 18,uint 16怎么会是0x 5000呢???我什么都不明白!这非常令人沮丧...

7uzetpgm

7uzetpgm1#

是的!我忘了C结构有对齐/打包问题!
使用ref-struct,您可以在定义结构时添加第二个参数{packed: true}...

const QuerySessionStatusStruct = StructType({
    ShortName: ref.types.uchar,         //  1
    LongName: ArrayType('uchar', 8),    //  9
    Type: ref.types.uchar,              // 10
    Characteristics: ref.types.uchar,   // 11
    Rows: ref.types.uint16,             // 13
    Cols: ref.types.uint16,             // 15
    CodePage: ref.types.uint16,         // 17
    Reserved: ref.types.uchar           // 18
 }, {packed: true});

现在输出是正确的!

RC is: 0
Long Name is: MAINFRAM
Rows is: 24

相关问题