26 (изменено: leshenkosa, 2014-03-21 17:19:34)

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Помогите, пожалуйста с передачей строк в DWX.
Пробую подключить длл написанную на delphi 7.
Описание ф-ции


function fWriteDoc(Idtypedoc:Integer; Idsenddoc:integer; IDWAY:Integer;
             BlockInfo: PChar; SenderKODOTD:Integer; SenderKODUS:Integer; Note: PChar;
             Datedoc:TDateTime; SendNote:PChar; ParentIDDOC:Integer):Integer;
             stdcall;  external Name;

Как правильно описать входные параметры? Как правильно передавать строку PChar?

Я пробовал объявить так:
Set Wrap = CreateObject("DynamicWrapperX")

Wrap.Register "ElDocDll.dll", "fWriteDoc", "i=lllsllsdsl", "f=s", "r=l"

При вызове фц-ции пишет что не верно заданы параметры
Вот тут вызов ф-ции:


IdTypeDoc = 83
IdSendDoc = id
IDWay = 0
BlockInfo = "" 
'      pBlockInfo = Wrap.StrPtr(BlockInfo, "s")
'      MsgBox pBlockInfo
SenderKODOTD = 268
SenderKODUS = 0
Note = Zakaz & " " & DOsn & Spec
'      pNote = Wrap.StrPtr(note, "s")
'      MsgBox Note
Datedoc = now
SendNote = ""
'      pSendNote = Wrap.StrPtr(SendNote, "s")
ParentIDDOC = 0 
res = Wrap.fWriteDoc(IdTypeDoc, IdSendDoc, IDWay, BlockInfo, SenderKODOTD, SenderKODUS, Note, Datedoc, SendNote, ParentIDDOC)

27

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Что-то не пойму. Описание вы приводите для fSendDoc, а регистрируете fWriteDoc.

28

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Ошибся ф-цией, сейчас поправлю

29 (изменено: leshenkosa, 2014-03-21 17:32:39)

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

После того как загрузил новую версию отсюда yuripopov.ucoz.net/load/0-0-0-8-20 и скопировал в system32 вообще стал ругаться на строку

Set Wrap = CreateObject("DynamicWrapperX")

С этим разобрался так

Set Wrap = CreateObject("DynamicWrapperX.2")

30

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Вам надо старую версию разрегистрировать, а новую зарегистрировать. У неё CLSID другой.

31 (изменено: leshenkosa, 2014-03-21 17:49:36)

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Что делать со строками в ф-циях? Integer в делфи это параметр "l" правильно? Дата и время это по-моему 8-байтное с плавающей точкой, передается параметром "d".
Не пойму никак с PChar что делать, перепробовал много всего ошибки лезут.
При чем если передавать в функцию не переменной, а статической строкой "Test1", то все работает отлично.
Какая-то особенность Vbscript в работе со строками, не пойму какая.

32

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Что за ошибки и от кого сообщение о них приходит?

33

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Простите за беспокойство, но после обновления DWX до 2 версии все заработало. Строки передаются корректно, информация в базу пишется. Спасибо за помощь.

34 (изменено: maksim32, 2014-03-21 18:51:59)

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Здравствуйте, Юрий. Я обычно работаю за Windows XP, но сегодня я запускал программу на восьмёрочке. На Windows XP x32/x64, Windows 7 x32/x64 работает, а на Windows 8 x64 - нет. Ничего не пишет даже, доходя до строчки создания окна. Типы пробовал менять, но не помогло. Вот та неработающая часть программы:

+ открыть спойлер
var IDI_APPLICATION=0x7F00, IDC_ARROW=0x7F00, CS_VREDRAW=0x1, CS_HREDRAW=0x2,
 CS_DBLCLKS=0x8, CS_OWNDC=0x20, WS_OVERLAPPEDWINDOW=0xCF0000,
 WS_VISIBLE=0x10000000, WS_EX_TOPMOST=8, WS_POPUP=0x80000000, WM_DESTROY=0x2,
 WM_ACTIVATE=0x6, WM_CHAR=0x102, WM_SETCURSOR=0x20, WM_QUIT=0x12;

function WNDCLASSEX(){
 // UINT, UINT, WNDPROC, int, int, HINSTANCE, HICON, HCURSOR, HBRUSH, LPCTSTR, LPCTSTR, HICON
 var a=["cbSize","style","lpfnWndProc","cbClsExtra","cbWndExtra","hInstance",
  "hIcon","hCursor","hbrBackground","lpszMenuName","lpszClassName","hIconSm"];
 for(var i in a)this[a[i]]=arguments[i];
 this._const="uupllhhhhpph";
}
function getStructWin(struct){
 var types=struct._const, // строка типов в стандарте DynamicWrapperX
  size=0, // размер структуры (вначале исходной, потом возвращаемой)
  data; // информация для внесения в стуктуру
 for(var i=0;i<types.length;i++)size+=DWXTypes[types.charAt(i).toLowerCase()]; // Вычисляем размер структуры /*на строку память не выделится!!*/
 var ns=DWX.MemAlloc(size,1); // MemFree() // выделение памяти в БАЙТАХ // создание структуры (new struct)
 size=0;i=0;
 for(var p in struct){ // заполняем структуру
  if(p=="_const")continue; // исключаем из структуры МОЮ строку типов
  data=struct[p];
  if(data==null)data=0;
  DWX.NumPut(data,ns,size,types.charAt(i)); // заносим данные data в стуктуру ns со смещением size
  size+=DWXTypes[types.charAt(i++).toLowerCase()];
 }
 return ns; // возвращаем преобразованную структуру
}
function WndProc(hWnd,uMsg,wParam,lParam){ // Callback function
 switch(uMsg){
  case WM_DESTROY:
   Close=1;
   break;
 }
 return DWX.DefWindowProcW(hWnd,uMsg,wParam,lParam);
}

function InitWindow(){
 DWX.Register("user32","LoadIconW","i=hp","r=h");
 DWX.Register("user32","LoadCursorW","i=hp","r=h")
 DWX.Register("user32","RegisterClassExW","i=p","r=t"); // ATOM
 var pWndProc=DWX.RegisterCallback(WndProc,"i=huul","r=l");
 var szClass="Class_name";
 var myWClass=new WNDCLASSEX((bit==32)?48:80, CS_VREDRAW|CS_HREDRAW|CS_DBLCLKS|CS_OWNDC,
  pWndProc, 0, 0, hModule, DWX.LoadIconW(0,IDI_APPLICATION),
  DWX.LoadCursorW(0,IDC_ARROW), 0, 0, szClass, 0);
 var wc=getStructWin(myWClass);
 if(DWX.RegisterClassExW(wc)==0){WSH.Echo("Ошибка при регистрации класса.");return false}
 DWX.Register("user32.dll","CreateWindowExA","i=ussullllhhhl","r=h"); // i=DWORD,LPCTSTR,LPCTSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID r=HWND
 var szTitle="My window";
 hWnd=DWX.CreateWindowExA(0,szClass,szTitle,WS_OVERLAPPEDWINDOW|WS_VISIBLE,
  20,20,500,400,0,0,hModule,0);
 //  hWnd=DWX.CreateWindowExA(WS_EX_TOPMOST,szClass,szTitle,WS_POPUP, 0,0,800,600,0,0,hModule,0);
 if(hWnd==0){WSH.Echo("Ошибка при создании окна.");return false}
 return true;
}

var DWX=new ActiveXObject("DynamicWrapperX");
var bit=DWX.Bitness(); // разрядность процесса
// типы по стандарту DynamicWrapperX в БАЙТАХ (строковые - 0)
var DWXTypes={"l":4,"u":4,"m":8,"q":8,"h":bit/8,"p":bit/8,"n":2,"t":2,"c":1,"b":1,"f":4,"d":8,"w":0,"s":0,"z":0,"v":0};
DWX.Register("kernel32","GetModuleHandleW","i=p","r=h"); // i=(LPCTSTR); r=HMODULE
DWX.Register("user32","DefWindowProcW","i=hupp","r=l"); // i=(HWND, UINT, WPARAM, LPARAM); r=LRESULT
DWX.Register("user32","ShowWindow","i=hl","r=l"); // i=(HWND, int); r=BOOL
DWX.Register("user32","UpdateWindow","i=h","r=l"); // i=(HWND); r=BOOL
var hModule=DWX.GetModuleHandleW(0);
var hWnd=0;
var Close=0;
if(!InitWindow())WSH.Quit(); // hWnd
DWX.ShowWindow(hWnd,1);
DWX.UpdateWindow(hWnd);
do{WSH.Sleep(200);}while(Close==0);

35

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Да, я с этим тоже сталкивался. В регистрации WndProc нужно задать wParam и lParam типом "h" или "p", т.е. меняющим размер в соответствии с битностью.

36 (изменено: maksim32, 2014-03-21 20:13:29)

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Точно, спасибо! Странно, что в остальных 64-битных версиях винды работало.
Похожая проблема с IDirect3DDevice9::CreateVertexBuffer (типы uuuuph). Тоже только в WinNT6.2x64 не работает.
Ещё, волнует вопрос: обязательно ли освобождать память (DWX.MemFree), ведь по завершению процесса память сама, по-идее, высвобождается? Что особенного происходит после выполнения DWX.MemAlloc? Чем он лучше DWX.Space, память после использования которого не требуется очищать?

37 (изменено: YMP, 2014-03-21 20:23:10)

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Могу только предположить, что там обнулённая память выделяется, а в восьмёрке нет. Поэтому в верхней части wParam и lParam оказывается мусор, если писать их как 32-битные в 64-битном процессе.

Да, по завершении процесса память освобождается, поэтому, если разово выделяются небольшие объёмы, то можно и не освобождать. Space возвращает строковую переменную, и тут проблема в том, что скриптовый движок может памятью строки манипулировать по своему усмотрению. Он-то думает, что это строка, а у вас там что угодно может храниться. Могут быть проблемы из-за этого.

38

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

YMP пишет:

Значение имеет битность процесса, а не ОС. Т.е. если скрипт выполнять 32-битным интерпретатором — тем, который в папке SysWOW64 — то будут использоваться 32-битные DLL.

Спасибо, YMP.
Сделал примерно так: Батник для регистрации DynamicWrapperX 2.0 (x32, x64) и вызова функций из 32/64-битных библиотек.

Может, кому окажется полезным.

39

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Dragokas
Возвращаемое значение FindWindow и первый параметр ShowWindow — хэндл, поэтому лучше для них задать тип "h". Возможно, значения оконных хэндлов и не выходят на данный момент за пределы 32 бит, но за будущее ручаться мы ведь не можем. Что там придёт в голову разработчикам Windows.

40

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Подскажите, как в буфер (MemAlloc) вставить строку (или скопировать другой буфер) со смещением, если StrPut (как и StrGet) не работают со смещением, как, например, NumPut?

41

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Вот так, например:


DWX.StrPut("Hello", pBuf + Offset, "s")

42 (изменено: maksim32, 2014-06-19 15:49:54)

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Но ведь в x64 системах указатели типа VT_UI8, а движком JScript не поддерживаются (с ними нельзя выполнять арифметические операции). Или в данном случае от этого не зависит?
А если буферы копировать (часть одного буфера заменить другим), то это побайтово в цикле тогда делать?

43

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Ну, MemAlloc такой тип вернёт только, если тип VT_R8 окажется недостаточен. А это 53 бита, т.е. до числа 0x1FFFFFFFFFFFFF включительно будет VT_R8. Думаете, система может выдать память с более высоких адресов? Хм... Поручиться я тут не могу, конечно.

Можно, в принципе, добавить параметр смещения в строковые функции. Что касается копирования участков памяти, то я думал, не сделать ли метод MemCopy. Раз он реально нужен, то тоже можно добавить. Хотя можно и RtlMoveMemory зарегистрировать и использовать.


DWX.Register("kernel32.dll", "RtlMoveMemory", "i=pph");
DWX.RtlMoveMemory(Dest, Source, Size);

44 (изменено: maksim32, 2014-06-19 17:02:54)

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Но RtlMoveMemory замещает опять же без смещения. И смещение тоже придётся делать с помощью сложения, которое не всегда допустимо (имею ввиду те, высокие, адреса).
Может добавить MemCopy со смещением, тогда и строки можно будет копировать, не боясь указателей типа VT_UI8? Хотя можно расширить функционал с помощью RegisterCode, но я в asm не силён.

45

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

maksim32 пишет:

Может добавить MemCopy со смещением, тогда и строки можно будет копировать, не боясь указателей типа VT_UI8?

Тогда нужно будет два смещения — к исходному и целевому адресу. Как-то громоздко получается. Либо сделать их необязательными и определять по алгоритму: если указаны 3 параметра, то это 2 адреса и размер; 5 параметров = адреса со смещениями и размер. Надо подумать. Или, может, сделать метод для операций с такими типами.

А всё потому, что в МС поленились добавить два типа в 64-битные движки. Неужели так трудно было?

46

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

MemCopy(Address, Source, Length [,Offset1] [,Offset2]));
Address - базовый адрес; Source - адрес замещаемого блока памяти; Length - количество байт на замену; Offset1 - смещение к исходному, Offset2 - к целевому. Хотя... можно и одним смещением обойтись, вызвав её 2 раза.
Метод для операций — сложение (+отрицательные чисела), которое нужно будет только для x64. Не знаю что лучше.

В функции RegisterCode преобразуется hex-строка (по-идее же). Можно было бы вынести это как отдельную функцию. Чтобы избежать костылей типа таких:

function hex2mem(str){var l=str.length-str.length%2, ptr=DWX.MemAlloc(l/2+1,1);
 for(var i=0,q=0;i<l;i+=2,q++)DWX.NumPut("0x"+str.substr(i,2)-0,ptr,q,"b");
 return ptr;
}

47

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Да, в принципе, можно бы и в конце их указывать. Но есть одно "но" — хотелось бы избежать разнобоя с NumGet/NumPut. По моему опыту такие вещи обычно раздражают, когда в одной функции так, а в другой этак. Думаю, ничего страшного даже если они обязательными бы были — два нуля поставить недолго.


DWX.MemCopy(SrcAddr, 0, DestAddr, 0, BytesToCopy);

Про hex2mem (и наоборот) тоже были мысли. Иногда удобная вещь. Например, глянуть, что находится где-то в памяти.


DWX.MemRead(SrcAddr, Offset, BytesToRead [, BytesPerGroup] [, GroupsPerLine]);
DWX.MemWrite(HexStr, DestAddr, Offset [, BytesToWrite]) 

Последние два параметра в MemRead — число байт в группе и групп на строке, для удобства обзора. Хотя отформатировать и средствами скрипта не проблема, конечно, так что, может, это и лишнее.

48

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

YMP пишет:

А всё потому, что в МС поленились добавить два типа в 64-битные движки. Неужели так трудно было?

Это да. Они много чего поленились сделать. Указатели в тип Real теперь переводи

Согласен, два нуля - недолго. MemRead/MemWrite, я лично, считаю полезным. На этапе debug'а скорость выполнения не так важна, как в готовом алгоритме. А побайтово составлять буфер, используя substr и сложение строк для поллучения  - неоптимально.

49

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

YMP пишет:

Ну, MemAlloc такой тип вернёт только, если тип VT_R8 окажется недостаточен. А это 53 бита, т.е. до числа 0x1FFFFFFFFFFFFF включительно будет VT_R8. Думаете, система может выдать память с более высоких адресов? Хм... Поручиться я тут не могу, конечно.

Почитал немного про память в х64. На данный момент для адресов используются 48 нижних бит (да и то только с Windows 8.1), причём это ограничение на уровне процессора. Так что VT_R8 хватит с запасом. Есть, правда, ещё память ядра, у которой верхние биты заполняются единицами, так что числа формально получаются больше. Но в эту память у приложений допуска нет.

Т.е. есть две зоны: 0 - 00007FFF'FFFFFFFF и FFFF8000'00000000 - FFFFFFFF'FFFFFFFF. В сумме это 256 терабайт, так что смысла расширять адрес дальше нет.

http://en.wikipedia.org/wiki/X86-64_vir … RESS-SPACE

50

Re: WSH: обсуждаем DynamicWrapperX от YMP - 2

Большое спасибо за полезное разъяснение.
Я пытаюсь реализовать буферизированный вывод элементов структур. Чтобы скопировать информацию из структуры в буфер хотел воспользоваться RtlCopyMemory, но при её регистрации происходит ошибка: функция не найдена в библиотеке. Ни в ntdll, ни в kernel32. А RtlMoveMemory находит. Не пойму в чём дело. Или вообще нужно как-то по-другому составлять буфер?
Вот пример:

+ открыть спойлер
var DWX=WScript.CreateObject("DynamicWrapperX");
var bit=DWX.Bitness(); // разрядность процесса
var dwxsize={l:4,u:4,m:8,q:8,h:bit/8,p:bit/8,n:2,t:2,c:1,b:1,f:4,d:8}; // размеры типов

function ld0n(val,n){val+="";while(val.length<n)val="0"+val;return val}
function cnv_num(val,f,t){return parseInt(val,f).toString(t).toUpperCase()} // Lower
function gethex(addr,size){
 for(var i=0,str="";i<size;i++)str+=ld0n(cnv_num(DWX.NumGet(addr,i,"b"),10,16),2);
 return str;
}

DWX.Register("advapi32.dll","GetTokenInformation","i=hupup","r=l"); // HANDLE,enum,LPVOID,DWORD,PDWORD; BOOL
DWX.Register("kernel32.dll","GetCurrentProcess","r=h"); // void; HANDLE
DWX.Register("advapi32.dll","OpenProcessToken","i=hup","r=l"); // HANDLE,DWORD,PHANDLE; BOOL
DWX.Register("kernel32.dll","LocalFree","i=h","r=h");
DWX.Register("kernel32.dll","CloseHandle","i=h","r=l");
DWX.Register("ntdll.dll","RtlMoveMemory","i=ppu"); // VOID UNALIGNED,const VOID UNALIGNED,SIZE_T; VOID

// буфер для последующего вывода
var BUFFER=DWX.MemAlloc(256,1),nBUFFER=0;

// добавляем в буфер какую-нибудь информацию
var test_str="Another info\0";
DWX.RtlMoveMemory(BUFFER+nBUFFER,test_str,test_str.length*2);
nBUFFER+=test_str.length*2;

var TOKEN_QUERY=0x0008;
var phToken=DWX.MemAlloc(dwxsize.h,1);
var hProcess=DWX.GetCurrentProcess();
DWX.OpenProcessToken(hProcess,TOKEN_QUERY,phToken);
var hToken=DWX.NumGet(phToken,0,"h");
var uSizeToken=dwxsize.p*2+28;
var ptiUser=DWX.MemAlloc(uSizeToken);
DWX.GetTokenInformation(hToken,1,ptiUser,uSizeToken,0);

// ещё добавляем информацию (User SID)
DWX.RtlMoveMemory(BUFFER+nBUFFER,DWX.NumGet(ptiUser,0,"p"),28);
nBUFFER+=28;

DWX.MemFree(ptiUser);
DWX.CloseHandle(hToken);
DWX.MemFree(phToken);
DWX.CloseHandle(hProcess);

// выводим буфер
WScript.Echo(gethex(BUFFER,nBUFFER));