|
|
表格:通过ExecuteExcel4Macro调用WinAPI实现
函数:
- function 数据入内存(数组缓冲){ //返回内存句柄
- const 数据操作=new DataView(数组缓冲);
- const 总字节=数组缓冲.byteLength;
- let 偏移=i=0,待写数据=[],写入字节=[];
- while(总字节>偏移){
- if(总字节-偏移>=4){待写数据[i]=数据操作.getInt32(偏移,true);写入字节[i]=4;i++;偏移+=4;}
- else{if(总字节-偏移>=2){待写数据[i]=数据操作.getInt16(偏移,true);写入字节[i]=2;i++;偏移+=2;}
- else{if(总字节-偏移==1){待写数据[i]=数据操作.getInt8(偏移,true);写入字节[i]=1;i++;偏移++;}}}
- }
- const 执行宏调用=ExecuteExcel4Macro;
- const 内存句柄=执行宏调用(`CALL("Kernel32","GlobalAlloc","JJJ",${0x42},${总字节})`);
- if(内存句柄){ //申请内存空间,会返地址
- const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`);
- for(偏移=i=0;i<写入字节.length;i++){ //库Kernel32.dll和NtDll.dll里都有RtlMoveMemory
- 执行宏调用(`CALL("Kernel32","RtlMoveMemory","2JNJ",${内存地址+偏移},${待写数据[i]},${写入字节[i]})`); //写入
- 偏移+=写入字节[i];
- }
- 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`); //解锁全局内存对象
- return 内存句柄; //返回
- }else{console.log("未能分配内存!");}
- }
- function 内存取数据(内存句柄){ //返回数组缓冲
- const 执行宏调用=ExecuteExcel4Macro;
- const 总字节=执行宏调用(`CALL("Kernel32","GlobalSize","JJ",${内存句柄})`); //内存对象空间大小
- let 偏移,i,读取字节=[],读出数据;
- for(偏移=i=0;偏移<总字节;i++){
- if(总字节-偏移>=4){读取字节[i]=4;偏移+=4;}
- else{if(总字节-偏移>=2){读取字节[i]=2;偏移+=2;}
- else{if(总字节-偏移==1){读取字节[i]=1;偏移++;}}}
- }
- const 数组缓冲=new ArrayBuffer(总字节); //用于存储读出的数据
- const 数据操作=new DataView(数组缓冲);
- const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`);
- if(内存地址){ //var 文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址},${127})`);
- for(偏移=i=0;偏移<总字节;i++){
- 读出数据=执行宏调用(`CALL("Kernel32","RtlMoveMemory","1NJJ",${内存地址},${内存地址+偏移},${读取字节[i]})`); //读出
- if(读取字节[i]==4){数据操作.setInt32(偏移,读出数据,true);偏移+=4;}
- else{if(读取字节[i]==2){数据操作.setInt16(偏移,读出数据,true);偏移+=2;}
- else{if(读取字节[i]==1){数据操作.setInt8(偏移,读出数据,true);偏移++;}}}
- }
- 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`); //解锁内存对象,以释放资源
- return 数组缓冲; //返回
- }else{console.log("未找到内存地址!");}
- }
复制代码
测试函数:
- function 数据字符串内存读写联合测试(){
- const 执行宏调用=ExecuteExcel4Macro;
- let 字符串="ABCD123"; //7字节字符串,需要8字节空间
- const 字符串内存句柄=字符串到内存(字符串); /*****写入字符串*****/
-
- console.clear();
- let 取得字符串=内存取字符串(字符串内存句柄); /*****读取字符串*****/
- console.log("直接读字符串:"+取得字符串+"\t结束!");
-
- let 数据数组缓冲=内存取数据(字符串内存句柄); /*****读取数据*****/
- 显示数组缓冲(数据数组缓冲); /*****显示数据*****/
- 执行宏调用(`CALL("Kernel32","GlobalFree","JJ",${字符串内存句柄})`); //释放内存
-
- let 数组缓冲=new ArrayBuffer(0x30); //准备数据
- let 数据操作=new DataView(数组缓冲);
- 数据操作.setInt32(0,0x34333231,true); //小端序4321
- 数据操作.setInt32(4,0x38373635,true);
- 数据操作.setInt32(8,0x3039,true);
- 数据操作.setInt32(0x10,0x44434241,true); //小端序DCBA
- 数据操作.setInt32(0x14,0x48474645,true);
- 数据操作.setInt32(0x18,0x4C4B4A49,true);
- 数据操作.setInt32(0x1C,0x504F4E4D,true);
- 数据操作.setInt32(0x20,0x54535251,true);
- 数据操作.setInt32(0x24,0x58575655,true);
- 数据操作.setInt32(0x28,0x5A59,true);
-
- let 数据内存句柄=数据入内存(数组缓冲); /*****写入数据*****/
-
- let 取出字符串=内存取字符串(数据内存句柄); /*****读取字符串*****/
- console.log("数据取成字符串:"+取出字符串+"\t结束!");
-
- let 取出数组缓冲=内存取数据(数据内存句柄); /*****读取数据*****/
- 显示数组缓冲(取出数组缓冲); /*****显示数据*****/
-
- 执行宏调用(`CALL("Kernel32","GlobalFree","JJ",${数据内存句柄})`); //释放内存
- }
- function 显示数组缓冲(组缓冲){
- const 数据操作=new DataView(组缓冲); //操作对象
- let 字节数据,高位,低位,数据=[],字符=[],数据串=字符串='';
- let 四分隔,八分隔,十六分隔;
- for(let i=0;i<组缓冲.byteLength;i++){
- if((i+1)%16==0){十六分隔='\n';}else{十六分隔='';}
- if((i+1)%8==0){八分隔=' ';}else{八分隔='';}
- if((i+1)%4==0){四分隔=' ';}else{四分隔='';}
- 字节数据=数据操作.getInt8(i);
- 高位=(字节数据>>>4&0xF).toString(16).toUpperCase();
- 低位=(字节数据&0xF).toString(16).toUpperCase();
- 数据[i]=高位+低位;
- 数据串+=数据[i]+' '+四分隔+八分隔+十六分隔;
- if(!字节数据){字符[i]=' ';}else{字符[i]=String.fromCharCode(字节数据);}
- 字符串+=字符[i]+' ';
- }
- console.log("数据串:\n"+数据串+"\n字符串:"+字符串+'\n');
- }
- function 字符串到内存(字符串){ //返回内存句柄
- const 执行宏调用=ExecuteExcel4Macro;
- let 分段文本=[],分段字节=[],总字节=0,段长度=127; //可申请256字节内存,结束符1字节,汉字最长127
- for(let 起始=i=0;起始<字符串.length;起始+=段长度,i++){
- 分段文本.push(字符串.slice(起始,起始+段长度));
- 分段字节.push(分段文本[i].replace(/[^\x00-\xff]/g,'xx').length); //一个汉字占两个字节
- 总字节+=分段字节[i];
- } //分配内存 //分配GlobalAlloc对应销毁GlobalFree //分配GlobalAlloc对应销毁GlobalFree
- const 内存句柄=执行宏调用(`CALL("Kernel32","GlobalAlloc","JJJ",${2},${总字节+1})`);
- if(内存句柄){ //内存分配成功,然后锁写解内存。 //锁定内存对象,会返回其地址
- const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`);
- for(let 偏移字节=i=0;i<分段文本.length;i++){ //字符串(JS变量)分批复制到刚申请的内存中。分批是因为有限长
- 执行宏调用(`CALL("Kernel32","lstrcpynW","JJFJ",${内存地址+偏移字节},"${分段文本[i].replace(/\"/g,'\"\"')}",${分段字节[i]})`);
- 偏移字节+=分段字节[i]; //返回地址J。 //字符串中两个双引号解释成一个(VB语法)
- }
- 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`); //解锁内存对象,以释放资源
- return 内存句柄;
- }else{console.log("未能分配内存!");}
- }
- function 内存取字符串(内存句柄){ //返回字符串
- const 执行宏调用=ExecuteExcel4Macro,段长度=127;
- const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`); //锁定,获取内存地址
- if(内存地址){
- const 总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`); //内存文本字节数
- let 偏移字节=0,文本字符串=分段文本='';
- while(偏移字节<总字节){ //返回字符串F。 //返回超255字节时,也需要分段操作
- 分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段长度})`);
- //偏移字节+=执行宏调用(`CALL("Kernel32","lstrlenA","JC","${分段文本.replace(/["\n]/g,'x')}")`);
- 偏移字节+=分段文本.replace(/[^\x00-\xff]/g,'xx').length; //计算字符串字节数
- 文本字符串+=分段文本;
- } //解锁内存对象,以释放资源
- 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`);
- return 文本字符串;
- }else{console.log("未找到内存地址!");}
- }
复制代码
|
|