1

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

Продолжение темы: WSH: обсуждаем DynamicWrapperX от YMP.

2

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

Комрады, я продолжаю успешно использовать эту замечательную компоненту.
Вопрос у меня вот какой, будет ли кому интересен опыт допиливания ее,  с возможность обработки SEH/VEH исключений.

Дело в том, что я активно занимаюсь перехватом различных функций внутри 1С-ки (версий 7.7 и 8.2) для расширения возможностей движков.  Все нормально работает, пока в 1С не возникает нештатная ситуация. В обычном режиме (без перехвата), 1С-ка ругается на что-то, допустим на отсутствие какого-нить свойства объекта, выбрасывает предупреждение и далее продолжает нормально работать. Если вдруг это происходит в перехваченной функции, то 1С-ка после этого вылетает в космос.
Я давно хотел обернуть , IDispatch::Invoke в "транзакционные" скобки типа catch-try, даже проводил какие-то исследования в этом направлении, но вопрос мне казался через чур сложным, так что я бросал это занятие и обходил проблему какими-то другими способами. Но, в этот раз, все таки решил дожать ситуацию и вроде как это не очень и сложно оказалось.

Жду отклика.

3

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

Вы пишите, а мы почитаем. :-)

4

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

Для демонстрации ситуации, которая может привести к краху программы,  предлагаю рассмотреть следующий пример.
Попробуем выполнить с помощью DWX следующий код:

XOR EAX,EAX
MOV EAX,DWORD PTR DS:[EAX]

Вот скрипт, который выполнит данный код, после нажатия на кнопку "Test":

<html>
    <head>
        <script language="vbscript">
            Public Const HEAP_ZERO_MEMORY         = &h8
            Public Const PAGE_EXECUTE_READWRITE    = &h40
            
            Public Wrap
            Public oServ
                 
            Class Service
                Private hHeap
                Private Ref
                Private buf
            
                Private Sub Class_Initialize
                    Set Wrap = CreateObject("DynamicWrapperX")
                    Wrap.Register "kernel32", "HeapAlloc",    "i=lll",    "r=l"
                    Wrap.Register "Kernel32", "HeapFree", "i=lll","r=l"
                    Wrap.Register "kernel32", "GetProcessHeap", "r=l"
                    Wrap.Register "kernel32", "VirtualProtect" , "i=lllp", "r=l"
            
                    hHeap         = Wrap.GetProcessHeap()
                    buf            = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
                    res            = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
                    Wrap.VirtualProtect buf, 4, PAGE_EXECUTE_READWRITE, res
            
                    Wrap.NumPut &hC033,     buf, 0, "n"                'XOR EAX,EAX
                    Wrap.NumPut &h008B,     buf, 2, "n"                'MOV EAX,DWORD PTR DS:[EAX]
            
                    Wrap.RegisterAddr buf, "Test", "r=l"
                End Sub
                
                Private Sub Class_Terminate
                    Wrap.HeapFree hHeap, 0, buf
                    Wrap.HeapFree hHeap, 0, res
                End Sub
            End Class
            
            Set oServ = New Service
                
            
            Sub btnTest_onclick()
                MsgBox "Test"
                On Error Resume Next
                Test = Wrap.Test()
                MsgBox "Код ошибки: " & Hex(Err.Number)
            End Sub
         </script>
    </head>
    
    <body>
        <button id=btnTest>Test</button>    
    </body>
</html>

5

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

Если этот скрипт выполнить в режиме "hta", по программа закроется, как выполнившая недопустимую операцию.
Под IE ситуация лучше - тут видимо код оборачивается в SEH по умолчанию.

Моя цель была такая - поправить DWX так, чтобы он обернул код

Test = Wrap.Test()

в SEH и по крайней мере не приводил к краху программы.

6 (изменено: chessman, 2013-04-01 14:21:37)

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

Ниже привожу код, который на лету поправляет DWX, оборачивая вызовы IDispatch::Invoke в SEH.
Код несколько длинный, но зато удобный для внесения правок, поскольку идет с комментариями.

<html>
    <head>
        <script language="vbscript">
        
            Public Const HEAP_ZERO_MEMORY         = &h8
            Public Const PAGE_EXECUTE_READWRITE    = &h40
            
            Public Wrap
            Public oServ
                 
            Class Service
                Private hHeap
                Private buf
                Private buf1
            
                Private Sub Class_Initialize
                    Set Wrap = CreateObject("DynamicWrapperX")
                    Wrap.Register "kernel32", "HeapAlloc",    "i=lll",    "r=l"
                    Wrap.Register "Kernel32", "HeapFree", "i=lll","r=l"
                    Wrap.Register "kernel32", "GetProcessHeap", "r=l"
                    Wrap.Register "kernel32", "VirtualProtect" , "i=lllp", "r=l"
            
                    hHeap                 = Wrap.GetProcessHeap()
                    res                    = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
                    
                    pObj                 = Wrap.GetIDispatch(Wrap)
                    num                    = Wrap.NumGet(pObj, 4) 'Увеличим на счетчик ссылок, чтоб никогда не выгружался
                    Wrap.NumPut    num + 1, pObj, 4         
                    vt                     = Wrap.NumGet(pObj)
                    IDispatch_Invoke     = Wrap.NumGet(vt, 6 * 4)
            
                    If Wrap.NumGet(IDispatch_Invoke, 0, "b") = &h68 Then
                        Exit Sub
                    End If
            
                    sz_buf        = 140
                    buf            = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sz_buf)
                    Wrap.VirtualProtect buf, sz_buf, PAGE_EXECUTE_READWRITE, res
            
                    'Оборачиваем в SEH
                    SEH IDispatch_Invoke, 9, buf
            
                    Wrap.VirtualProtect vt, 4, PAGE_EXECUTE_READWRITE, res
                    Wrap.NumPut buf, vt, 6 * 4
                    Wrap.VirtualProtect vt, 4, Wrap.Numget(res), res
                    
                    
                    buf1    = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
                    Wrap.VirtualProtect buf, 4, PAGE_EXECUTE_READWRITE, res
                        
                    Wrap.NumPut &hC033,     buf1, 0, "n"                'XOR EAX,EAX
                    Wrap.NumPut &h008B,     buf1, 2, "n"                'MOV EAX,DWORD PTR DS:[EAX]
                        
                    Wrap.RegisterAddr buf1, "Test", "r=l"
                End Sub
                
                Private Sub Class_Terminate
                    Wrap.HeapFree hHeap, 0, res
                    Wrap.HeapFree hHeap, 0, buf1
                End Sub
                
                Private Function SEH(callAddr, numParams, buf)
                    szParams = numParams * 4
            
                    Wrap.NumPut &h68,             buf, 0, "b"                    'PUSH SEH-обработчик
                    Wrap.NumPut buf + 52 + szParams,    buf, 1                '
                    Wrap.NumPut &h64,             buf, 5, "b"                    'PUSH DWORD PTR FS:[0]
                    Wrap.NumPut &h35FF,         buf, 6, "n"                    '
                    Wrap.NumPut 0,                buf, 8                        '    
                    Wrap.NumPut &h64,             buf, 12, "b"                'MOV DWORD PTR FS:[0],ESP
                    Wrap.NumPut &h2589,         buf, 13, "n"                '
                    Wrap.NumPut 0,                buf, 15                        '
                    Wrap.NumPut &h60,             buf, 19, "b"                'PUSHAD    Сохраняем регисты
                    
                    For j = 0 To numParams - 1
                        Wrap.NumPut &hFF,             buf, 20 + j * 4, "b"    'PUSH DWORD PTR SS:[ESP+(10 + numParams) * 4]
                        Wrap.NumPut &h74,             buf, 21 + j * 4, "b"
                        Wrap.NumPut &h24,             buf, 22 + j * 4, "b"
                        Wrap.NumPut 40 + szParams,     buf, 23 + j * 4, "b"
                    Next
            
                    Wrap.NumPut    &hE8,                                     buf, 20 + szParams, "b"        'CALL ....callAddr
                    Wrap.NumPut    callAddr - (buf +21 + szParams + 4),    buf, 21    + szParams            '
            
                    'Сохраняем значение ф-и в стек
                    Wrap.NumPut &hC483,        buf, 25 + szParams, "n"            'ADD ESP,20
                    Wrap.NumPut &h20,         buf, 27 + szParams, "b"            '
                    Wrap.NumPut &h09EB,        buf, 28 + szParams, "n"            'JMP SHORT  ------------------------------------+
                    Wrap.NumPut &h1C2444C7,    buf, 30 + szParams                'MOV DWORD PTR SS:[ESP+1C], DISP_E_EXCEPTION    |    
                    Wrap.NumPut &h80020009, buf, 34 + szParams                '                                                |
                    Wrap.NumPut &h61,         buf, 38 + szParams, "b"            'POPAD                                            |
                    Wrap.NumPut &h64,         buf, 39 + szParams, "b"            'POP DWORD PTR FS:[0]        <-------------------+
                    Wrap.NumPut &h058F,     buf, 40 + szParams, "n"            '
                    Wrap.NumPut 0,            buf, 42 + szParams                    '
                    Wrap.NumPut &hC483,     buf, 46 + szParams, "n"            'ADD ESP,4
                    Wrap.NumPut &h4,         buf, 48 + szParams, "b"            '
                    Wrap.NumPut &hC2,         buf, 49 + szParams, "b"            'RETN 24
                    Wrap.NumPut szParams,    buf, 50 + szParams, "n"            '
            
                    '___SEH    
                    '__cdecl _except_handler(
                    '        struct _EXCEPTION_RECORD     *ExceptionRecord,
                     '        void                         *EstablisherFrame,
                     '        struct _CONTEXT             *ContextRecord,
                     '        void                         *DispatcherContext
                     '        )
                    Wrap.NumPut &h0C24448B,    buf, 52 + szParams                'MOV EAX,DWORD PTR SS:[ESP+C]        pFrame                
                    Wrap.NumPut &h08244C8B,    buf, 56 + szParams                'MOV ECX,DWORD PTR SS:[ESP+8]        pContext
                    Wrap.NumPut &hE983,     buf, 60 + szParams, "n"            'SUB ECX,20                            вычисляем правильную позицию стека
                    Wrap.NumPut &h20,         buf, 62 + szParams, "b"            '
                    '======Восстанавливаем ESP======
                    Wrap.NumPut &h8889,     buf, 63 + szParams, "n"            'MOV DWORD PTR DS:[EAX+C4], ECX        mov (CONTEXT ptr [eax]).regEsp, 
                    Wrap.NumPut &hC4,        buf, 65 + szParams                '                        
                    '======Восстанавливаем EIP======
                    Wrap.NumPut &h80C7,     buf, 69 + szParams, "n"            'MOV DWORD PTR DS:[EAX+B8], addr    mov (CONTEXT ptr [eax]).regEip, offset ....
                    Wrap.NumPut &hB8,        buf, 71 + szParams                '
                    Wrap.NumPut buf + 30 + szParams,    buf, 75 + szParams    '
                    '======Сбрасываем бит у ExceptionFlags======
                    Wrap.NumPut &h04244C8B,    buf, 79 + szParams                'MOV ECX,DWORD PTR SS:[ESP+4]        ExceptionRecord    
                    Wrap.NumPut &hFE046180,    buf, 83 + szParams                'AND BYTE PTR DS:[ECX+4],FE           очищаем флаг EXCEPTION_NONCONTINUABLE у ExceptionFlags
                    '======Выходим из обработки исключения======
                    Wrap.NumPut &hB8,         buf, 87 + szParams, "b"            'MOV EAX,ExceptionContinueExecution
                    Wrap.NumPut 0,            buf, 88 + szParams                '
                    Wrap.NumPut &hC3,         buf, 92 + szParams, "b"            'RETN
                End Function
            End Class
            
            Set oServ = New Service

            Sub btnTest_onclick()
                MsgBox "Test"
                'On Error Resume Next
                Test = Wrap.Test()
                MsgBox "Error code: " & Hex(Err.Number)
            End Sub
         </script>
    </head>
    
    <body>
        <button id=btnTest>Test</button>    
    </body>
</html>

7

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

Код вроде бы нормально отрабатывает. Идея правильная, конечно, исключения надо обрабатывать. Я как-то уже делал это на ассемблере, но подробности подзабылись. Особо сложного чего-то действительно нет. К сожалению, на x64 технология изменилась и, как я понял, сложнее будет реализовать.

8 (изменено: chessman, 2013-04-01 19:10:18)

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

Честно говоря не знаю, что именно изменилось для x64, но у меня еще есть вариант с оберткой в VEH. В принципе тоже самое, только мне показалось менее удобно. Может этого будет достаточно для x64.

9

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

Отличная утилита. Я написал hta-скрипты "пианино" с использование midi библиотеки. А также находил окно VirtualDub, брал команды списка меню окна и управлял им. Всё работает.
Тем более, я написал шаблон, облегчающий подключение всех функций.
Однако вчера споткнулся и не знаю, почему CreateFile даёт ошибку. Мне нужно открыть мэппинг файла и на лету его читать-изменять оперативно. Одна моя утилита рабоотает в фоне и использует 4кб файл как псевдо-интерфейс (управляю параметрами изменением этого файла в Hiew). Hiew-дамп использовать несколько неудобно, решил в hta прямо dhtml путями менять параметры.
Вот скрипт.

Что я делаю не так?

Спасибо!

Post's attachments

dump.hta 5.74 kb, 7 downloads since 2013-04-03 

You don't have the permssions to download the attachments of this post.

10

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

Вероятно, проблема в том, что результат операции GENERIC_READ | GENERIC_WRITE сохраняется JScript'ом в виде знакового целого числа (тип VT_I4), а учитывая, что в GENERIC_READ в старшем бите стоит 1, число получается отрицательное. А тип параметра у вас задан как uint.

Можно изменить тип параметра на int, но тогда может возникнуть та же ошибка при передаче GENERIC_READ самого по себе, т.к. он имеет тип VT_R8 (дробное число двойной точности), является положительным и выходит за пределы положительных значений int (максимум там 0x7FFFFFFF).

Можно заменить "GENERIC_READ | GENERIC_WRITE" на "GENERIC_READ + GENERIC_WRITE" — здесь результатом будет положительное число типа VT_R8. Либо изобрести собственный флаг GENERIC_READ_WRITE со значением 0xC0000000.

Возможно, я зря встроил эту проверку на валидность значения числа с точки зрения знаковости/беззнаковости. Я думал, это поможет против каких-нибудь случайных ошибок, но начинаю думать, что от этой фичи больше неудобства, чем пользы.

11 (изменено: Dragokas, 2014-02-01 20:50:05)

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

Приветствую!
YMP, спасибо за огромнейшую работу !!!

Подскажите, а как вызвать функцию из 32-битной бибилиотеки в 64-битной ОС ?
Если запускать cscript file.vbs из 32-битной cmd.exe, то все нормально отрабатывает.

Post's attachments

GoogleTranslateAPI by raxp - call to vbs.zip 536.99 kb, 11 downloads since 2014-02-01 

You don't have the permssions to download the attachments of this post.

12

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

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

13

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

Если хотите гарантировать, что скрипт будет выполняться в 32-битном процессе, то можно в начале скрипта через метод Bitness проверять битность, и если она 64, то запускать вторую копию скрипта с явным указанием 32-битного интерпретатора, а первую копию завершать.

14 (изменено: maksim32, 2014-02-28 23:23:44)

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

YMP, огромное спасибо за вашу разработку!!!
Подскажите, как с помощью DynamicWrapperX воспользоваться Direct3D в JScript?

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

В C++ пишут так:


LPDIRECT3D9 pDirect3D=NULL;
bool InitDirectX(void)
{
    if((pDirect3D=Direct3DCreate9(D3D_SDK_VERSION)) == NULL) return(false);
    D3DDISPLAYMODE stDisplay;
    if(FAILED(pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &stDisplay)))
        return(false);
    <...>
}

На Fasm:


d3d9  MACRO  func, this, arglist :VARARG
 mov   eax , [this]
 mov   eax , [eax]
 IFB <arglist>
      INVOKE [IDirect3D9Vtbl. func][eax], this
 ELSE
      INVOKE [IDirect3D9Vtbl. func][eax], this, arglist
 ENDIF
ENDM

IDirect3D9Vtbl    STRUC
 <...>
 STDMETHOD    GetAdapterDisplayMode, :PTR IDirect3D9, :UINT, :PTR D3DDISPLAYMODE,
 <...>
IDirect3D9Vtbl    ENDS

 <...>
.COD
 invoke    Direct3DCreate9, D3D_SDK_VERSION
 mov    pd3d, eax
 d3d9    GetAdapterDisplayMode, pd3d, D3DADAPTER_DEFAULT, ADDR d3ddm
 <...>

А на JScript никак не получается:


var DWX=new ActiveXObject("DynamicWrapperX");
function InitDirect3D(){
 DWX.Register("d3d9.dll","Direct3DCreate9","i=u","r=p");
 var D3D_SDK_VERSION=32;
 var pDirect3D=DWX.Direct3DCreate9(D3D_SDK_VERSION);
 if(pDirect3D==0){WScript.Echo("Интерфейс Direct3D недоступен!");return 1}
 var D3DADAPTER_DEFAULT=0;
 var pDisplay=DWX.StrPtr(DWX.Space(16,""));
 var Direct3D=DWX.ObjGet(pDirect3D); // получаем интерфейс IUnknown Direct3D
 Direct3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT,pDisplay); // не работает ни один метод ((
 return 0;
}

Так тем более не работает:


var DX=new ActiveXObject("DynamicWrapperX");
function InitDirect3D(){
 DX.Register("d3d9.dll","Direct3DCreate9","i=u","r=p");
 var D3D_SDK_VERSION=32;
 var pDirect3D=DX.Direct3DCreate9(D3D_SDK_VERSION);
 var D3DADAPTER_DEFAULT=0;
 var IDirect3D9=new Object();
 DX.NumPut(pDirect3D,IDirect3D9); // здесь пишет ошибку...
 IDirect3D9.GetAdapterDisplayMode(D3DADAPTER_DEFAULT);
 return 0;
}

15

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


Direct3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT,pDisplay);

Проблема в том, что в скриптах так можно вызывать только методы объектов, поддерживающих интерфейс IDispatch. С IUnknown так работать не получится. Нужно получать адрес соответствующего метода, регистрировать его в DWX через RegisterAddr и потом уже вызывать как метод DWX. Т.е. работать с методами как с функциями.

Указатель на интерфейс, возвращаемый Direct3DCreate9, указывает на другой указатель, который уже указывает на список указателей (адресов) методов (т.е. фактически на адрес метода QueryInterface). Методы IDirect3D9 должны идти после методов IUnknown.


pIUnknown -> pVTable -> pQueryInterface
                        pAddRef
                        pRelease
                        pCheckDepthStencilMatch
                        ...
                        pGetAdapterDisplayMode
                        ...

Если вас такой геморрой не пугает, могу попробовать написать пример вызова метода.

16

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

Был бы очень рад примеру! Адрес метода не знаю как из COM-интерфейса получить. Спасибо!

17

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

Вот так у меня работает. При регистрации и вызове методов нужно учитывать, что все они имеют первым параметром указатель на интерфейс (хотя в описании об этом не говорится). Порядок методов в VTable нужно смотреть не в описании интерфейса (там методы по алфавиту), а в header-файле.


DWX = new ActiveXObject("DynamicWrapperX");
PtrSize = DWX.Bitness() / 8;

DWX.Register("d3d9.dll","Direct3DCreate9","i=u","r=p");
D3D_SDK_VERSION = 32;
pDirect3D = DWX.Direct3DCreate9(D3D_SDK_VERSION);
if(pDirect3D == 0){WScript.Echo("Интерфейс Direct3D недоступен!");}
pVTable = DWX.NumGet(pDirect3D, 0, "p")
pGetAdapterDisplayMode = DWX.NumGet(pVTable, 8 * PtrSize, "p");
DWX.RegisterAddr(pGetAdapterDisplayMode, "GetAdapterDisplayMode", "i=pup", "r=l");

D3DADAPTER_DEFAULT = 0, D3D_OK = 0;
pDisplay = DWX.MemAlloc(32, 1);
ret = DWX.GetAdapterDisplayMode(pDirect3D, D3DADAPTER_DEFAULT, pDisplay);
if (ret == D3D_OK) {
    Width = DWX.NumGet(pDisplay, 0, "u");
    Height = DWX.NumGet(pDisplay, 4, "u");
    RefreshRate = DWX.NumGet(pDisplay, 8, "u");
    WSH.echo(Width, Height, RefreshRate);
}
else {
    WSH.echo("Ошибка при вызове GetAdapterDisplayMode: " + ret);
}

DWX.MemFree(pDisplay);

Методы в VTable (файл d3d9.h):


DECLARE_INTERFACE_(IDirect3D9, IUnknown)
{
    /*** IUnknown methods ***/
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
    STDMETHOD_(ULONG,Release)(THIS) PURE;

    /*** IDirect3D9 methods ***/
    STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;
    STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
    STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;
    STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT Format) PURE;
    STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE;
    STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter,D3DDISPLAYMODE* pMode) PURE;
    STDMETHOD(CheckDeviceType)(THIS_ UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed) PURE;
    STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat) PURE;
    STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels) PURE;
    STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat) PURE;
    STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT TargetFormat) PURE;
    STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps) PURE;
    STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE;
    STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface) PURE;
    
    #ifdef D3D_DEBUG_INFO
    LPCWSTR Version;
    #endif
};

18 (изменено: maksim32, 2014-03-01 16:04:42)

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

Спасибо!! Всё отлично работает! Вы мне о-очень помогли!
А какая разница между параметрами "p" и "v"? Зачем нужен "v"? Изменяется ли размер в зависимости от разрядности хоста?

19

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

p — это указатель. Для чисел влияет только на размер (4 или 8 байт в зависимости от битности процесса). В случае строки функции передастся указатель на неё, в случае объекта — указатель на объект. v — указатель на структуру VARIANT. В таких структурах передаются методам их аргументы в скриптовых языках. Если тип указан как "v", то значение из такой структуры не извлекается, как обычно, а функции передаётся указатель на саму структуру. Предполагается, что функция знает, что с ней делать.

По коду выше есть одно соображение: указатель pDirect3D в конце работы с интерфейсом, как я понял, положено освобождать. Т.е. нужно зарегистрировать метод Release


pRelease = DWX.NumGet(pVTable, 2 * PtrSize, "p");
DWX.RegisterAddr(pRelease, "Release", "i=p");

а где-то в конце вызвать


DWX.Release(pDirect3D);

20 (изменено: maksim32, 2014-03-01 22:58:23)

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

Спасибо за важное замечание. Я заметил, что не только "h", "p" меняют область значений в зависимости от битности процесса, но и "f". В документации об этом нет информации.

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

Вот, если нужно, код:

var DWX=new ActiveXObject("DynamicWrapperX");
var DWXTypes=["l","u","m","q","h","p","n","t","c","b","f","d"];//,"w","s","z","v"];
var str="x"+DWX.Bitness()+"\n";
var t0;
var t1="яяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяя"; // 1111 1111
var t2="UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"; // 0101 0101
var ptr1=DWX.StrPtr(t1,"cp1251");
var ptr2=DWX.StrPtr(t2,"cp1251");

for(var i=0;i<DWXTypes.length;i++){
 str+=DWXTypes[i]+"\t"+DWX.NumGet(ptr1,0,DWXTypes[i])+" \t\t "+DWX.NumGet(ptr2,0,DWXTypes[i])+"\n";
}
WSH.Echo(str);

21

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

Нет, там ошибка была в коде DWX. Спасибо за репорт! Попробуйте версию 2.0.0.1, сейчас должно быть одинаково.

Кстати, текст диалоговых окон можно копировать по Ctrl-C.

22

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

YMP пишет:

Нет, там ошибка была в коде DWX. Спасибо за репорт! Попробуйте версию 2.0.0.1, сейчас должно быть одинаково.

Кстати, текст диалоговых окон можно копировать по Ctrl-C.

Привет, Юрий!
Это официальная версия?

Я так понимаю, что ошибка была не критичная?

23

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

Да, можно сказать, официальная. Ошибка связана с сохранением в переменную дробного числа типа Float из регистра. Т.е., например, если функция возвращает такое значение или NumGet читает его из памяти. Я дробные сохраняю в переменные как Double, и вот забыл в 64-битной версии прописать преобразование.

Кроме того ещё ObjGet вызывал исключение, если его вызвать без сохранения результата в переменную (смысла нет так вызывать, но всё-таки). Это тоже исправлено.

24

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

Спасибо.

25 (изменено: maksim32, 2014-03-04 02:34:41)

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

YMP пишет:

Нет, там ошибка была в коде DWX. Спасибо за репорт! Попробуйте версию 2.0.0.1, сейчас должно быть одинаково.

Кстати, текст диалоговых окон можно копировать по Ctrl-C.

Вам огромное спасибо за предоставленные возможности и оперативную техподдержку!
Библиотека работает отлично).