51

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

Судя по всему, это инлайновая функция. Т.е. она ниоткуда не экспортируется, а просто в то место, где она вызывается, компилятор вставляет её код.

В последней версии DWX есть метод MemCopy. Проще всего его использовать. А для чтения памяти в хекс-строку есть метод MemRead.

52

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

YMP, прошу прощение за неграмотность, но у меня не получилось реализовать нормальный рабочий манифест под вторую версию. Смысл в использовании Вашей библиотеки без ее регистрации в реестре. Буду признателен за помощь.
Также хотел уточнить будут ли отличатся манифесты на 86 и 64-битных версиях ОС?

53

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

JSman
Возможно, CLSID не поправили? Сейчас потестил, у меня для обеих битностей работают такие манифесты.

wscript.exe.manifest


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

<assemblyIdentity
  type="win32"
  name="wscript.exe"
  version="1.0.0.0" /> 

  <dependency>
          <dependentAssembly>
              <assemblyIdentity
                  type="win32"
                  name="dynwrapx.sxs"
                  version="2.1.0.0" />
          </dependentAssembly>
  </dependency>

</assembly>

dynwrapx.sxs.manifest


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

<assemblyIdentity
    type="win32"
    name="dynwrapx.sxs"
    version="2.1.0.0" />

<file name="dynwrapx.dll">
     <comClass
        clsid="{89565276-A714-4a43-912E-978B935EDCCC}"
        threadingModel="Both"
        progid="DynamicWrapperX" />
</file>

</assembly>

54

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

Да... Это я не смотрел за обновлениями. Огромное спасибо за MemCopy и MemRead/MemWrite!!
Вопрос как скрипту запросить права администратора? Запускаю скрипт обычным wscript.exe, в скрипт же не вставишь manifest.

55

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

Не знаю, не озадачивался таким вопросом. Наверно, как-то можно запросить повышение прав через API.

56

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

YMP пишет:

JSman
Возможно, CLSID не поправили? Сейчас потестил, у меня для обеих битностей работают такие манифесты.

Так и получилось. Причем на 64-битной ОС отлично работает 32-битная сборка. Получился универсальный вариант. Большое спасибо!

57 (изменено: maksim32, 2014-10-19 20:01:07)

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

На разных архитектурах размер типа LRESULT изменяется (4/8). В справке к DynamicWrapperX он относится к знаковым целым 32-битным (l). По-идее UINT_PTR=WPARAM=LPARAM=LRESULT=LONG_PTR="p".

typedef LONG_PTR LRESULT;
+ YMP

58

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

Повысить права скрипту можно только его перезапуском от другого пользователя или так:
http://msdn.microsoft.com/en-us/library … s.85).aspx

59

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

maksim32 пишет:

На разных архитектурах размер типа LRESULT изменяется (4/8). В справке к DynamicWrapperX он относится к знаковым целым 32-битным (l).

typedef LONG_PTR LRESULT;

Да, действительно, надо будет исправить. Спасибо!

60 (изменено: maksim32, 2014-10-19 20:34:57)

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

Кстати, вопрос, почему для указателей мы используем беззнаковый тип ("p"), ведь эти типы все знаковые?:
WNDPROC, LPCTSTR, LPCWSTR, UINT_PTR, WPARAM, LPARAM, LONG_PTR, LRESULT, LPVOID, LPMSG, PDWORD, PHANDLE, PSID, ULONG_PTR, PULONG_PTR...
В тоже время для дескрипторов используем знаковый ("h") (как оно и есть). Или вообще без разницы знаковые они или нет?

61

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

Ну, указатель — это адрес. Может ли адрес быть отрицательным?

Вообще-то сейчас я убрал проверку на знаковость для входных параметров. В 1-й версии нельзя было для параметра с типом "p" или "u" подать отрицательное число. Но проблема в том, что в скриптовых языках у нас нет полного контроля за типами, да и сам набор типов не полон. Так что в некоторых случаях такая строгая проверка вызывала неудобства.

Поэтому на данный момент разница между "p" и "h", "u" и "l", и т.д. — чисто мнемоническая. Просто чтобы видно было, знаковый или беззнаковый параметр в определении функции. Указатель или хэндл. По факту в обоих случаях передаётся тот же набор битов, а как его интерпретировать, функция знает сама.

Но для возвращаемых значений разница остаётся. Поскольку здесь уже сам DWX должен откуда-то знать, как ему интерпретировать, например, 32-битное число 0xFFFFFFFF: если как "l", тогда это -1 и её можно поместить в тип VT_I4; если как "u", тогда число положительно и выходит за диапазон VT_I4, нужно использовать тип VT_R8. Тогда и отображаться это число будет корректно, если вы захотите посмотреть, что вернула функция, и арифметические операции с ним будут правильны.

62 (изменено: maksim32, 2014-11-03 19:40:59)

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

А как работать с типом long double? И можно ли ограничить (расширить) диапазон чтения строки StrGet (типа Bytes — размер в байтах)? Например,

var DWX=WScript.CreateObject("DynamicWrapperX.2");
var MyStruct=DWX.MemAlloc(14+2*4,0);
DWX.MemWrite("48656C6C6F2C20667269656E6473",MyStruct,14); // Hello, friends
DWX.NumPut(0x6C65645F,MyStruct,14,"u");
DWX.NumPut(0x00657465,MyStruct,18,"u");
var str=DWX.StrGet(MyStruct,0,"s");
DWX.MemFree(MyStruct);
WScript.Echo(str); // хочу получить "Hello, friends"

В данном случае можно обойтись строчкой

str=str.substr(0,14);

Второй случай, с необходимостью расширения строки:

var str1="Hello,\0World"; str1+=" my friend!"; // длина строки 23
WScript.Echo(DWX.MemRead(DWX.StrPtr(str1),str1.length*2,2,0));
// length=23; echo = 4800 6500 6C00 6C00 6F00 2C00 0000 5700 6F00 7200 6C00 6400 2000 6D00 7900 2000 6600 7200 6900 6500 6E00 6400 2100
// в JScript поддерживается работа со строками, содержащими терминальный 0
var MyStruct=DWX.MemAlloc(23*2+4,0);
DWX.StrPut(str1,MyStruct,0,"w");
DWX.NumPut(0x6C65645F,MyStruct,46,"u");
WScript.Echo(DWX.MemRead(MyStruct,23*2+4,2,0));
// echo = 4800 6500 6C00 6C00 6F00 2C00 0000 0100 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 FFFF 5F64 656C
// NumPut записала строку до нуля (не всю)
DWX.MemCopy(DWX.StrPtr(str1),MyStruct,23*2); // теперь запишем всю строку
var str2=DWX.StrGet(MyStruct,0,"w"); // и получим её
WScript.Echo(str2.length); // её длина стала 6
DWX.MemFree(MyStruct);

В этом случае уже нужно пользоваться MemCopy.
Получается лучше сразу использовать MemCopy для чтения и записи строки; для чтения:

var str2=DWX.Space(23,"");
DWX.MemCopy(MyStruct,DWX.StrPtr(str2),23*2);

Полный код:

+ открыть спойлер
var DWX=WScript.CreateObject("DynamicWrapperX.2");
var MyStruct=DWX.MemAlloc(14+2*4,0);
DWX.MemWrite("48656C6C6F2C20667269656E6473",MyStruct,14); // Hello, friends
DWX.NumPut(0x6C65645F,MyStruct,14,"u");
DWX.NumPut(0x00657465,MyStruct,18,"u");
var str0=DWX.StrGet(MyStruct,0,"s");
DWX.MemFree(MyStruct);
WScript.Echo(str0); // хочу получить "Hello, friends"
// str0=str0.substr(0,14);
var str1="Hello,\0World"; str1+=" my friend!"; // длина строки 23
WScript.Echo(DWX.MemRead(DWX.StrPtr(str1),str1.length*2,2,0));
// length=23; echo = 4800 6500 6C00 6C00 6F00 2C00 0000 5700 6F00 7200 6C00 6400 2000 6D00 7900 2000 6600 7200 6900 6500 6E00 6400 2100
// в JScript поддерживается работа со строками, содержащими терминальный 0
var MyStruct=DWX.MemAlloc(23*2+4,0);
DWX.StrPut(str1,MyStruct,0,"w");
DWX.NumPut(0x6C65645F,MyStruct,46,"u");
WScript.Echo(DWX.MemRead(MyStruct,23*2+4,2,0));
// echo = 4800 6500 6C00 6C00 6F00 2C00 0000 0100 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 FFFF 5F64 656C
// NumPut записала строку до нуля (не всю)
DWX.MemCopy(DWX.StrPtr(str1),MyStruct,23*2); // теперь запишем всю строку
var str2=DWX.StrGet(MyStruct,0,"w"); // и получим её
WScript.Echo(str2.length); // её длина стала 6
str2=DWX.Space(23,"");
DWX.MemCopy(MyStruct,DWX.StrPtr(str2),23*2);
WScript.Echo(DWX.MemRead(DWX.StrPtr(str2)-4,23*2+4,2,0));
// 2E00 0000 4800 6500 6C00 6C00 6F00 2C00 0000 5700 6F00 7200 6C00 6400 2000 6D00 7900 2000 6600 7200 6900 6500 6E00 6400 2100
// Всё в порядке
DWX.MemFree(MyStruct);

63

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

Параметр для длины строки сделать можно, конечно. Хотя логичнее задавать его в символах, а не байтах. Но тут не всё так просто в многобайтных кодировках вроде UTF-8 или каких-нибудь восточно-азиатских.

А как работать с типом long double?

А где он реально нужен? Возвращать его в скрипт не в чем. Для 64-битного целого типы хотя и не используются в JScript, но существуют, а тут типа вообще нет. По логике он бы должен называться VT_R10. Если возвращать в VT_R8, будет обрезаться по точности. Да и по величине может не влезть.

Передача его в функцию и возврат из неё нигде не оговорены, по кр. мере я не нашёл. Видимо, передаётся и возвращается по указателю. А в Visual Studio он вообще не отличается от double: Type long double.

64 (изменено: maksim32, 2014-11-04 20:09:57)

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

Да, стандартных функций, передающих long double, я не встречал. Но в структуре встретиться может. В принципе, можно было бы использовать 10-символьную строку (10-байтовый участок памяти). А если вычисления производить, тогда преобразовать в double.
Я делаю объект struct, чтобы легче было работать с winapi (но скорость теряется). В него и хотел добавить поддержку long doube.
Пример использования "структуры" (поиск всех dll в папке windows):

+ открыть спойлер
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}; // размеры типов

var defWINAPI={
 /*  4 */ LONG:"l", INT:"l", BOOL:"l", HRESULT:"l", NTSTATUS:"l", "int":"l",
 /* u4 */ ULONG:"u", UINT:"u", DWORD:"u", PUINT:"u", LPUINT:"u", ULONG32:"u", "enum":"u",
 /*  8 */ INT64:"m", LONGLONG:"m",
 /* u8 */ UINT64:"q", ULONGLONG:"q", DWORDLONG:"q", ULONG64:"q",
 /*  $ */ HANDLE:"h", HWND:"h", HMODULE:"h", HLOCAL:"h", HINSTANCE:"h", HICON:"h", HCURSOR:"h", HBRUSH:"h", HDROP:"h", PVOID:"h", INT_PTR:"h", LONG_PTR:"h", /*?*/ 
 /* u$ */ WNDPROC:"p", LPCTSTR:"p", LPCWSTR:"p", UINT_PTR:"p", WPARAM:"p", LPARAM:"p", LPVOID:"p", ULONG_PTR:"p", PULONG_PTR:"p", LRESULT:"p", SIZE_T:"p" /*unsigned*/, LPMSG:"p", PDWORD:"p", PHANDLE:"p", PSID:"p",
 /*  2 */ SHORT:"n",
 /* u2 */ USHORT:"t", WORD:"t", PWORD:"t", LPWORD:"t", WCHAR:"t", OLECHAR:"t", wchar_t:"t",
 /*  1 */ CHAR:"c", CCHAR:"c",
 /* u1 */ UCHAR:"b", BYTE:"b", PBYTE:"b", BOOLEAN:"b",
 /*  4 */ FLOAT:"f",
 /*  8 */ DOUBLE:"d",
 BSTR:"w", LPWSTR:"w", LPOLESTR:"w",
 LPSTR:"s", LPCSTRL:"s"
};
var struct={ // добавить описание обязательно к этому объекту
 use: [], // для очистки
 create: function(name,crtaddr){ // если crtaddr задан числом, отличным от 0, то память на структуру выделяться не будет
  if(typeof(struct[name])=="undefined"){WScript.Echo("Error, struct "+name+" is undefined!");WScript.Quit();return false} // исключение
  var obj={
   addr: crtaddr?crtaddr:DWX.MemAlloc(struct[name].$_size,1), // при crtaddr не выделяем память
   type: name,
   put: function(aStr,data){struct.put(this,aStr,data)},
   get: function(aStr){return struct.get(this,aStr)},
   size: struct[name].$_size,
   _nid: crtaddr?-1:struct.use.length // номер структуры, для destroy
  };
  if(!crtaddr)struct.use.push(obj);
  return obj
 },
 put: function(obj,aStr,data){
  var tp=struct[obj.type],sz=0; aStr=aStr.split(".");
  for(var i=0;i<aStr.length-1;i++){sz+=tp[aStr[i]].offset;tp=tp[aStr[i]].obj;}
  tp=tp[aStr.pop()];
  DWX.NumPut(data,obj.addr,(sz+tp.offset),tp.type);
 },
 get: function(obj,aStr){ // use: 'var SysTimeInfo=struct.create("SYSTEM_TIME_OF_DAY_INFORMATION"); SysTimeInfo.get("CurrentTime.LowPart");' - вернёт значение поля, а 'SysTimeInfo.get("CurrentTime");' вернёт указатель на поле
  var tp=struct[obj.type],sz=0,tmp; aStr=aStr.split(".");
  var charonly=false;
  for(var i=0;i<aStr.length;i++){
   tmp=aStr[i].split(/(\[)|(\])/g); // разделяем каждый элемент строки адреса по []
   tp=tp[tmp[0]]; sz+=tp.offset;
   if(tmp[1]){tmp=tmp[1]-0;charonly=true;if(tp.obj)sz+=tp.obj.$_size*tmp; else sz+=dwxsize[tp.type]*tmp;} // tmp=eval(tmp[1])-0; (убрал eval)
    else{charonly=false;}
   if(tp.obj)tp=tp.obj; else break;
  }
  if(tp.$_size)return obj.addr+sz; // если это не "лист" дерева структуры, то просто возвращаем указатель на память
  // DebugStr+=typeof(tmp)+": "+tmp+"\n";
  if((!tp.count)||charonly/*(tmp>=0) - bad*/)return DWX.NumGet(obj.addr,sz,tp.type); // (tmp>=0), где tmp=[srt,n] - чтобы при запросе str[n] не выводилась оставшаяся часть строки - bag solution (tp.count - количество элементов массива)
  // else: tmp=[str] => массив (пока обработчики только строки)
   if(tp.elemtype=="WCHAR")return DWX.StrGet(obj.addr+sz,"w"); // если это строка
   if(tp.elemtype=="UCHAR")return DWX.StrGet(obj.addr+sz,"s"); // если это строка
    WScript.Echo("TODO: добавить обработчик для типа: "+tp.elemtype); // debug
   return obj.addr+sz;
 },
 define: function(name,str,pack){ // pack - выравнивание для структуры (default(0): по максимальному члену)
  var obj={},sz=0,arg,tp;
  var align=1,tost; // new vars (renamed)
  if(!pack)pack=8; // размеры всех типов не превышают 8
  str=str.split(";");
  for(var i=0;i<str.length;i++){
   arg=str[i].split(/\s/gm);
   if(arg.length<2)continue;
   tp=defWINAPI[arg[0]];
   if(typeof(tp)=="undefined"){WScript.Echo("Error, type "+arg[0]+" is undefined!");WScript.Quit();return false} // исключение
   /* // без выравнивания:
   if(typeof(tp)=="string"){obj[arg[1]]={type:tp,offset:sz};sz+=dwxsize[tp];}
    else{obj[arg[1]]={obj:tp,offset:sz};sz+=tp.$_size}
   
   // с выравниванием:
   if(typeof(tp)=="string"){ // если тип является простым
    align=Math.max(align,dwxsize[tp]); // высчитываем общее выравнивание структуры
    tost=Math.min(pack,dwxsize[tp]); // выравнивание текущего члена (исключительно при изменении выравнивания pack)
    sz=Math.ceil(sz/tost)*tost; // отступ по выравниванию
    
    obj[arg[1]]={type:tp,offset:sz}; // создание члена в структуре
    sz+=dwxsize[tp];
   } else { // иначе (составным)
    align=Math.max(align,tp.$_align);
    tost=Math.min(pack,tp.$_align);
    sz=Math.ceil(sz/tost)*tost;
    
    obj[arg[1]]={obj:tp,offset:sz};
    sz+=tp.$_size;
   }
   */
   // с множественным обозначением (массивами)   
   var data,kdata;
   tost=arg[1].split(/(\[)|(\])/g); // temp var
   if(tost.length==1){data=arg[1];kdata=1;}else{data=tost[0];kdata=tost[1]-0;} // kdata=eval(tost[1])-0; (убрал eval)
   
   if(typeof(tp)=="string"){ // простой тип
    align=Math.max(align,dwxsize[tp]); // общее выравнивание структуры
    tost=Math.min(pack,dwxsize[tp]);
    sz=Math.ceil(sz/tost)*tost;
    
    obj[data]={type:tp,offset:sz};
    if(kdata>1){obj[data].count=kdata;obj[data].elemtype=arg[0];} // если массив (кол-во членов больше 1)
    sz+=dwxsize[tp]*kdata;
   } else { // составной тип
    align=Math.max(align,tp.$_align);
    tost=Math.min(pack,tp.$_align);
    sz=Math.ceil(sz/tost)*tost;
    
    obj[data]={obj:tp,offset:sz};
    if(kdata>1){obj[data].count=kdata;obj[data].elemtype=arg[0];}
    sz+=tp.$_size*kdata;
   }
  }
  tost=Math.min(pack,align);
  sz=Math.ceil(sz/tost)*tost; // выравниваем последний элемент структуры, оставляя после ного пустоту (правило выравнивание последнего поля)
  obj.$_size=sz;
  obj.$_align=Math.min(align,pack); // для маленьких структур
  defWINAPI[name]=obj;
  struct[name]=obj;
 },
 destroy: function(obj){DWX.MemFree(obj.addr);obj.addr=0;struct.use[obj._nid]=null;},
 destroyAll: function(){
  var t; while(struct.use.length){t=struct.use.pop();if(t!=null)struct.destroy(t);}
 }
/* Пример структуры - результат struct.define("WIN32_FIND_DATAW","DWORD dwFileAttributes; FILETIME ftCreationTime; FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; DWORD nFileSizeHigh; DWORD nFileSizeLow; DWORD dwReserved0; DWORD dwReserved1; WCHAR cFileName[260]; WCHAR cAlternateFileName[14]"):
struct.WIN32_FIND_DATAW = defWINAPI.WIN32_FIND_DATAW = {
 "dwFileAttributes": {type: "u", offset: 0},
 "ftCreationTime": {
  obj: {
   "dwLowDateTime": {type: "u", offset: 0},
   "dwHighDateTime": {type: "u", offset: 4},
   $_size: 8,
   $_align: 4
  },
  offset: 4
 },
 "ftLastAccessTime": {
  obj: {
   "dwLowDateTime": {type: "u", offset: 0},
   "dwHighDateTime": {type: "u", offset: 4},
   $_size: 8,
   $_align: 4
  },
  offset: 12
 },
 "ftLastWriteTime": {
  obj: {
   "dwLowDateTime": {type: "u", offset: 0},
   "dwHighDateTime": {type: "u", offset: 4},
   $_size: 8,
   $_align: 4
  },
  offset: 20
 },
 "nFileSizeHigh": {type: "u", offset: 28},
 "nFileSizeLow": {type: "u", offset: 32},
 "dwReserved0": {type: "u", offset: 36},
 "dwReserved1": {type: "u", offset: 40},
 "cFileName": {type: "t", offset: 44, count: 260, elemtype: "WCHAR"},
 "cAlternateFileName": {type: "t", offset: 564, count: 14, elemtype: "WCHAR"},
 $_size: 592,
 $_align: 4
}
*/
}

// include
DWX.Register("kernel32.dll","FindFirstFileW","i=pp","r=h"); // LPCTSTR,LPWIN32_FIND_DATAW; HANDLE
DWX.Register("kernel32.dll","FindNextFileW","i=hp","r=l"); // HANDLE,LPWIN32_FIND_DATAW; BOOL
DWX.Register("kernel32.dll","FindClose","i=h","r=l"); // HANDLE; BOOL

// typedef
struct.define("FILETIME","DWORD dwLowDateTime; DWORD dwHighDateTime");
struct.define("WIN32_FIND_DATAW","DWORD dwFileAttributes; FILETIME ftCreationTime; FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; DWORD nFileSizeHigh; DWORD nFileSizeLow; DWORD dwReserved0; DWORD dwReserved1; WCHAR cFileName[260]; WCHAR cAlternateFileName[14]"); // MAX_PATH=260

// define
var INVALID_HANDLE_VALUE=-1;

function FindFiles(path){
 var Files=[];
 var FindFileData=struct.create("WIN32_FIND_DATAW");
 var hFind=DWX.FindFirstFileW(path,FindFileData.addr);
 if(hFind!=INVALID_HANDLE_VALUE){
  while(1){
   if((FindFileData.get("dwFileAttributes")&0x10)==0) // FILE_ATTRIBUTE_DIRECTORY=0x00000010
    Files.push(FindFileData.get("cFileName")); // если не дирректория
   if(DWX.FindNextFileW(hFind,FindFileData.addr)==0)break;
  }
  DWX.FindClose(hFind);
 }
 struct.destroy(FindFileData);
 return Files;
}

// main
var DllFiles=FindFiles("C:\\Windows\\*.dll");
WScript.Echo(DllFiles.join("\n"));

65

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

Т.е. вам реально попадались такие структуры или это чисто теоретически? Я думаю, этот тип используется внутри функций, чтобы в промежуточных вычислениях уменьшить потери в точности. А результат всё равно будет возвращён как double.

Да, про объект Struct я тоже думал и даже начал реализовывать некоторое время назад, как дочерний объект DWX. Синтаксис создания структуры, например, такой:


struct = DWX.Struct( "uwd", 1000, "Hello, world!", 33.44 );

Т.е. сначала список типов членов, потом их значения. И впоследствии доступ к членам по их порядковым номерам. Можно, наверно, и вариант с именованными членами сделать.


struct = DWX.Struct( "size:u name:w value:d", 1000, "Hello", 44.55 );

66 (изменено: maksim32, 2014-11-05 00:58:12)

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

Нет, чисто теоретически. Допустим мы сохраняем 3D-модель, представленную в виде структуры (работать со структурированными файлами проще).

Я первоначально структуры делал, используя конструкторы (этот код я уже присылал, когда у меня проблема с IDirect3DDevice9 была на Windows8 x64 (и осталась)):

+ открыть спойлер
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};

 // функция преобразования (создания) структуры из объекта JScript (без строк)
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 getStructJS(ns,struct){ /*строки!!*/
 var types=struct._const, size=0;
 for(var i in struct){
  struct[i]=DWX.NumGet(ns,size,types.charAt(i))
  size+=DWXTypes[types.charAt(i).toLowerCase()]; // получая размер параметра
 }
 return struct; // возвращаем преобразованную структуру
}

// typedef struct
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";
}

var IDI_APPLICATION=0x7F00, IDC_ARROW=0x7F00, CS_VREDRAW=0x1, CS_HREDRAW=0x2,
 CS_DBLCLKS=0x8, CS_OWNDC=0x20;

// использование:
DWX.Register("user32","LoadIconW","i=hp","r=h");
DWX.Register("user32","LoadCursorW","i=hp","r=h")
DWX.Register("user32","RegisterClassExW","i=p","r=t");
DWX.Register("user32","DefWindowProcW","i=hupp","r=l"); // HWND,UINT,WPARAM,LPARAM; LRESULT
DWX.Register("kernel32","GetModuleHandleW","i=p","r=h"); // i=(LPCTSTR); r=HMODULE

function WndProc(hWnd,uMsg,wParam,lParam){return DWX.DefWindowProcW(hWnd,uMsg,wParam,lParam);}
var hModule=DWX.GetModuleHandleW(0);
var pWndProc=DWX.RegisterCallback(WndProc,"i=hupp","r=l");
var szClass="DirectX9"; // То самое имя класса, которое мы будем регистрировать
// заполняем структуру и получаем её в нужном нам формате
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, к тому же бывали случаи, когда приходилось всем одинаковым типам (например, LRESULT) сменить их "значение" DWX, к тому же наличие типов в стиле winapi (хотя бы в комментариях) облегчает написание программы (в документациях они же используются). И к тому же мало возможностей. Вот и получился тот вариант struct. Хотел, кстати, ещё копирование структур/части структур сделать и ограничить вывод строк, но пока это "горло не резало" (об этом я уже здесь спрашивал).

Ещё думаю как сделать структуру с динамическим размером (но как выделить дополнительную память в уже имеющуюся структуру (и изменить смещения и т.п.) я не придумал), типа:

typedef struct {
  ...
  LONG nSize; // размер следующего поля
  WCHAR cText[nSize]; // массив длины не определённой изначально
  ...
} MYTMPSTRUCT;

67

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

Интересно, сколько их вообще, этих производных типов. Теоретически можно было бы их свести в какую-то таблицу и использовать в обозначениях типов параметров и т.п., но впечатление такое, что их куева туча и всё равно какие-то останутся не охваченными. Может быть, держать их в текстовом файле, который можно было бы постепенно пополнять по мере надобности.

Дополнительную память — ну, вряд ли. Перевыделять тогда память большего размера. Ведь нельзя гарантировать, что рядом с уже выделенной памятью будет свободное место для расширения.

68 (изменено: maksim32, 2014-11-05 11:35:18)

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

Типов таких очень много. В зависимости от используемых технологий. Я их по мере необходимости в тот список добавлял. В моём случае их можно добавлять непосредственно, можно написать defWINAPI["HMENU"]=defWINAPI["HANDLE"] или сделать функцию. Мне кажется что носить с собой текстовый файл будет неудобно, лучше, наверное, непосредственно в код вставлять.

Вот пример из структур сохранения игры (SAS.bt):

...
// Block 2: Players & Objects
struct tBlock02_Players_n_Objects
{
    tblockHeader header;
    int         nPlayers;
    tPlayer     players[nPlayers];
    int         nObjects;
    tObject     objects[nObjects];
} block2;

// Block 3: Garages
struct tBlock03_Garages
{
    tblockHeader header;
    int                 nGarages;
    byte                boolFreeBombs, boolFreeResprays;
    byte                boolRespraysDisabled;
    DWORD               unknown[8];
    tGarageVehiclesTown GarageVehicles[4];
    tGarage             Garages[nGarages];
} block3;
...

Как тогда происходит чтение/запись таких "полуструктурированных" файлов? Может она вначале в кучу всё считывает, а потом, считав и узнав размер, уже размечает память? Хотел сделать поддержку таких структур тоже.

69

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

Т.е. такие структуры хранятся в файле? Тогда значения nPlayers и т.п. там тоже есть и несложно вычислить размер массивов, а значит и структуры в целом.

70 (изменено: maksim32, 2014-11-06 20:02:15)

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

Отбой, не бывает таких структур. Этот файл со структурой интерпретируется не как сишная структура, всё считывается отдельно написанным кодом.

+ открыть спойлер

Да, можно, но заранее (перед прочтением поля структуры, содержащего размер) размера мы не знаем. И в ходе выполнения программы это количество и размер структуры соответственно может измениться. Я подумал, что можно допустим массив players в структуре представить указателем на связный список nPlayers элементов, а работать как с обычной структурой ("struct" это должен будет обеспечивать) в том числе и чтение/запись её. К тому же, создавая пустую такую структуру, предполагается, что nPlayers=0.

71 (изменено: maksim32, 2014-11-30 22:43:52)

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

Глобальные хуки устанавливаются только с использованием DLL.
http://www.prog.org.ru/index.php?topic= … #msg157278
Может добавить возможность устанавливать хуки для скриптов? Поставить хук на всё, а скрипту передавать только то, что требуется.

72

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

Для мыши и клавиатуры DLL не обязательна, если использовать WH_MOUSE_LL и WH_KEYBOARD_LL.

Ставить хук на всё, по-моему, незачем. От DLL требуется только callback-функция, причём для всех хуков она одинакова по набору параметров и возвращаемому значению. По идее функция может просто передавать свои параметры скрипту, а их обработка будет уже там, в зависимости от того, какой это хук. Вопрос в том, как осуществить эту передачу.

73

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

Здравствуйте, YMP! Спасибо, с низкоуровневыми хуками действительно работает.

Пытался получить имя файла с сервера и заметил падение хоста при использовании возвращаемого значения функции DWX.LastError(1).

+ открыть спойлер
function ld0n(val,n){val+=""; while(val.length<n)val="0"+val; return val;}
function alert(val){WScript.Echo(val);}

var DWX;
try{DWX=new ActiveXObject("DynamicWrapperX.2");}
catch(e){WScript.Echo("Ошибка. Не установлен компонент DynamicWrapperX 2.");WScript.Quit();}

// include <wininet.h>
DWX.Register("wininet.dll","InternetOpenW","i=puppu","r=h"); // LPCTSTR,DWORD,LPCTSTR,LPCTSTR,DWORD; HINTERNET
DWX.Register("wininet.dll","InternetConnectW","i=hpuppuup","r=h"); // HINTERNET,LPCTSTR,INTERNET_PORT,LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD_PTR; HINTERNET
DWX.Register("wininet.dll","InternetCloseHandle","i=h","r=l"); // HINTERNET; BOOL
DWX.Register("wininet.dll","HttpOpenRequestW","i=hpppppup","r=h"); // HINTERNET,LPCTSTR,LPCTSTR,LPCTSTR,LPCTSTR,LPCTSTR,DWORD,DWORD_PTR; HINTERNET
DWX.Register("wininet.dll","HttpQueryInfoW","i=huppp","f=l","r=l"); // HINTERNET,DWORD,LPVOID,LPDWORD,LPDWORD; BOOL

// defile
var NULL = 0;
var HTTP_QUERY_CONTENT_DISPOSITION = 47;
var INTERNET_OPEN_TYPE_PRECONFIG = 0;
var INTERNET_FLAG_RELOAD = 0x80000000;
var INTERNET_SERVICE_HTTP = 3;
var INTERNET_DEFAULT_HTTP_PORT = 80;
var INTERNET_FLAG_PRAGMA_NOCACHE = 0x00000100;

function GetUrlInfo(dwInfoLevel, FileURL){
 var result = "<Error>";
 var servname = FileURL.substr(0, FileURL.indexOf("/"));
 var objname = FileURL.substr(FileURL.indexOf("/")+1);
 var hInternet = DWX.InternetOpenW(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); 
 if(hInternet){
  var hConnect = DWX.InternetConnectW(hInternet, servname, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL/*""*/);
  if(hConnect){
   var hRequest = DWX.HttpOpenRequestW(hConnect, "GET", objname, NULL, NULL, NULL, INTERNET_FLAG_RELOAD || INTERNET_FLAG_PRAGMA_NOCACHE, NULL);
   if(hRequest){

    var size = 2048;
    var pBuffer = DWX.MemAlloc(size, 0);
    var pSizeBuffer = DWX.MemAlloc(4, 0); // DWORD
    DWX.NumPut(size, pSizeBuffer, 0, "u");
    if(DWX.HttpQueryInfoW(hRequest, dwInfoLevel, pBuffer, pSizeBuffer, NULL)) result = DWX.StrGet(pBuffer);
    else{
     // 12150: ERROR_HTTP_HEADER_NOT_FOUND (Не удалось найти запрошенный заголовок.)
     alert("Error: "+DWX.LastError(0)+"");
     alert(DWX.LastError(1)); // На этой строчке происходит crash
    }
    alert("Test alert"); // соответственно, не сработает
    DWX.MemFree(pBuffer);
    DWX.MemFree(pSizeBuffer);

    DWX.InternetCloseHandle(hRequest);
   }
   DWX.InternetCloseHandle(hConnect);
  }
  DWX.InternetCloseHandle(hInternet);
 }
 return result;
}

GetUrlInfo(HTTP_QUERY_CONTENT_DISPOSITION, "www.yandex.ru/images/today");
+ YMP

74

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

Спасибо за сообщение, ошибку исправил. Использовалось возвращаемое значение LoadString вместо указателя на переданный ей буфер.

75

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

Что делает недокументированная функция UseLastError?