Введение в использование скриптовых движков: Часть 2

Дата публикации 24 фев 2004

Введение в использование скриптовых движков: Часть 2 — Архив WASM.RU

Введение

Если вы помните, в предыдущей статье было рассказано об основах управления скриптовыми движками, в частности о том, как заставить выполняться простейший скрипт. В том примере было мало интересного - скрипт жил сам по себе и, отработав, просто возвращал управление основной программе. Сейчас настало время рассмотреть более полезные техники, а именно, как передать скрипту какие-нибудь параметры и наоборот - получить от него информацию (например, о результатах работы). В качестве иллюстрации рассмотрим такой пример:

screenshot

Сделаем так, чтобы текст в EditBox’е можно было изменять из скрипта.

В прошлый раз я говорил о том, что необходимым условием для использования COM-объекта является знание структуры его интерфейсов. Однако далеко не всегда такое возможно, как например в нашем случае. Например, так будет выглядеть скрипт, устанавливающий содержимое контрола Edit равным "some text":

Edit1.Text = "some sext"

Edit1 - это имя нашего объекта, а Text - свойство, подлежащее установке. Ясно, что никаких данных о структуре интерфейса из этого извлечь нельзя, поэтому нужно располагать некоторым средством, позволяющим вызывать методы по их именам. Такое средство есть, в COM оно известно, как "позднее связывание" (late binding).

LATE BINDING.

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

Выходом является использование интерфейса IDispatch, который возволяет вызвать нужную процедуру по ее имени. Он содержит следующие методы:

  • GetTypeInfoCount
  • GetTypeInfo
  • GetIDsOfNames
  • Invoke

(нет необходимости говорить о том, что IDispatch тоже наследуется от IUnknown).

Из этих методов нам интересны два последних, обычно их использование выглядит так: сначала методу GetIDsOfNames передается массив с адресами имен нужного метода (свойства) и его параметров, он этот массив просматривает и устанавливает соответствие между именем и некоторым числом, представляющим собой уникальный (в пределах интефейса) ID (обычно говорят “DISPID”) данного элемента. Далее этот DISPID передается методу Invoke, который и производит вызов процедуры.

Имя объекта

С именем объекта все гораздо проще – достаточно указать движку, что за именем “Edit1” скрывается объект.

Делается это при помощи вызова IActiveScript::AddNamedItem.

HRESULT AddNamedItem(LPCOLESTR pstrName, DWORD dwFlags);

pstrName – указатель на имя в формате WideCharacter.

dwFlags может принимать разные значения, в зависимости от поставленной задачи, мы укажем флаг SCRIPTITEM_ISVISIBLE, показывающий, что pstrName – это имя объекта и мы предоставляем средства для доступа к его методам и свойствам.

		mov edx, [pIActiveScript]
		mov edx, [edx]
		push SCRIPTITEM_ISVISIBLE
		push Item_name
		push [pIActiveScript]
		call dword [edx + AddNamedItem]

Теперь, когда движок встретит конструкцию Edit1.Method он вызовет метод IActiveScriptSite::GetItemInfo, чтобы получить интерфейс IDispatch, который контролирует данный объект.

HRESULT GetItemInfo(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppunkItem, ITypeInfo **ppTypeInfo);

pstrName – указатель на имя объекта.

dwReturnMask – показывает, какая именно информация запрашивается. Может принимать значения:

  • SCRIPTINFO_IUNKNOWN – запрашивается IUnknown
  • SCRIPTINFO_ITYPEINFO – запрашивается ITypeInfo

ppunkItem, ppTypeInfo – адреса переменных, в которые будут помещены указатели на интерфейсы. Здесь есть один момент, который заслуживает внимания – дело в том, что вышеописанный IDispatch – не едиственный способ осуществить связывание имен. В качестве альтернативы может использоваться интерфейс ITypeInfo, но мы не будем его реализовывать и все сделаем через IDispatch, поэтому если наш метод GetItemInfo получает параметр dwReturnMask с установленным SCRIPTINFO_ITYPEINFO, он должен будет вернуть 0 в ppTypeInfo.

Код (Text):
  1.  
  2. proc IActiveScriptSite_GetItemInfo, pi, pstrName, dwReturnMask, ppunkItem, ppTypeInfo
  3.         enter
  4.  
  5.         ;Сравниваем переданное имя с “Edit1”.
  6.         invoke lstrcmpW, [pstrName], Item_name
  7.         test eax, eax
  8.         jz @F
  9.  
  10.         mov eax, TYPE_E_ELEMENTNOTFOUND
  11.         return
  12.  
  13. @@:     mov eax, [dwReturnMask]
  14.  
  15.         cmp eax, SCRIPTINFO_IUNKNOWN
  16.         jz .IUnknown
  17.  
  18.         cmp eax, SCRIPTINFO_ALL_FLAGS
  19.         jz .IUnknown
  20.  
  21.         cmp eax, SCRIPTINFO_ITYPEINFO
  22.         jz .ITypeInfo
  23.  
  24.         mov eax, E_INVALIDARG
  25.         return
  26.  
  27. .IUnknown:    
  28.         mov eax, [ppunkItem]
  29.             mov edx, IDispatch
  30.             mov [eax], edx
  31.  
  32.             mov edx, [edx]
  33.             push IDispatch
  34.             call dword [edx + Addref]
  35.  
  36. .ITypeInfo: mov eax, [ppTypeInfo]
  37.             test eax, eax
  38.             jz @F
  39.  
  40.             and dword [eax], 0
  41.  
  42. @@:         mov eax, S_OK
  43.             return
  44.  

Теперь, чтобы вызвать нужный метод движок предпримет следующие действия:

  1. Использует метод QueryInterface, полученного IUnknown для получения указателя на IDispatch.
  2. С помощью GetIDsOfNames преобразует имена методов (свойств) в их идентификаторы.
  3. Вызовет нужный код с помощью Invoke

Следовательно, первое, что нам нужно сделать – подправить метод IUnknown::QueryInterface :

Код (Text):
  1.  
  2. proc IActiveScriptSite_QueryInterface, pi, iid, ppvObject
  3.         enter
  4.         invoke IsEqualGUID, [iid], IID_IUnknown
  5.         test eax, eax
  6.         jnz .s_ok_unk
  7.  
  8.         invoke IsEqualGUID, [iid], IID_IActiveScriptSite
  9.         test eax, eax
  10.         jnz .s_ok_unk
  11.  
  12.         invoke IsEqualGUID, [iid], IID_IActiveScriptSiteWindow
  13.         test eax, eax
  14.         jnz .s_ok_acw
  15.  
  16.         invoke IsEqualGUID, [iid], IID_IDispatch
  17.         test eax, eax
  18.         jnz .s_ok_dsp
  19.  
  20. .NoInterface:   mov eax, E_NOINTERFACE
  21.         return
  22.  
  23. .s_ok:      mov edx, [pIActiveScriptSite]
  24.                 mov edx, [edx]
  25.         push [pIActiveScriptSite]
  26.         call dword [edx + Addref]
  27.  
  28.         mov eax, S_OK
  29.         return
  30.  
  31. .s_ok_unk:  mov eax, [ActiveScriptSiteObject]
  32.         mov eax, [eax]
  33.         mov edx, [ppvObject]
  34.         mov [edx], eax
  35.         jmp .s_ok
  36.  
  37. .s_ok_acw:  mov eax, [ActiveScriptSiteObject]
  38.         mov eax, [eax + 4]
  39.         mov edx, [ppvObject]
  40.         mov [edx], eax
  41.         jmp .s_ok
  42.  
  43. .s_ok_dsp:  ;если iid == IDispath, то вернем указатель на него.
  44.  
  45.         mov eax, [ActiveScriptSiteObject]
  46.         mov eax, IDispatch
  47.         mov edx, [ppvObject]
  48.         mov [edx], eax
  49.         jmp .s_ok
  50.  

Теперь QueryInterface способен воспринимать GUID IDispatch (00020400-0000-0000-C000-000000000046), а сам IDispatch будет выглядеть так:

Код (Text):
  1.  
  2. IDispatch           dd IDispatch_vtable
  3.  
  4. ;первые 3 – методы IUnknown, общие для всех интерфейсов нашего
  5. объекта.
  6.  
  7. IDispatch_vtable    dd IActiveScriptSite_QueryInterface
  8.             dd IActiveScriptSite_AddRef
  9.             dd IActiveScriptSite_Release
  10.  
  11.             dd IDispatch_GetTypeInfoCount
  12.             dd IDispatch_GetTypeInfo
  13.             dd IDispatch_GetIDsOfNames
  14.             dd IDispatch_Invoke
  15.  

Методы GetTypeInfoCount и GetTypeInfo мы здесь рассматривать не будем – заменим их чем-нибудь вроде этого:

Код (Text):
  1.  
  2. proc IDispatch_GetTypeInfoCount, pi, pctinfo
  3.             enter
  4.             mov eax, [pctinfo]
  5.             mov dword [eax], 0
  6.             mov eax, S_OK
  7.             return
  8.  
  9. proc IDispatch_GetTypeInfo, pi, iTInfo, lcid, ppTInfo
  10.             enter
  11.             mov eax, DISP_E_BADINDEX
  12.             return
  13.  

А вот без Invoke и GetIDsOfNames не обойтись.

HRESULT GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId);

riid – reserved (всегда 0).

rgszNames – указатель на массив указателей на строки, содержащие имена (первый представляет собой имя метода/свойства, следующие - имена параметров).

cNames – количество элементов массива.

rgDispId – указатель на массив, в который будут помещены ID, соответствующие именам из rgszNames. Если имя не опознано, то в соответствующий элемент массива rgDispId должно быть помещено значение -1.

lcid нам не понадобится, т.к. предполагаем, что имена будут только на английском.

Вот примерная (и не совсем корректная) реализация:

Код (Text):
  1.  
  2. proc IDispatch_GetIDsOfNames, pi, riid, rgszNames, cNames, lcid, rgDispId
  3.         enter
  4.  
  5.         pushad
  6.  
  7.         mov esi, [rgszNames]
  8.         mov ebx, [rgDispId]
  9.  
  10.         lodsd
  11.  
  12.         invoke lstrcmpW, eax, szSetText
  13.         test eax, eax
  14.         jnz @F
  15.  
  16.         ;Пусть DISPID будет равен 1
  17.         mov dword [ebx], 1
  18.  
  19.         popad
  20.         mov eax, S_OK
  21.         return
  22.  
  23. @@:     or dword [ebx], -1
  24.         popad
  25.  
  26.         ;Было передано имя несуществующего элемента.
  27.         mov eax, DISP_E_UNKNOWNNAME
  28.         return
  29.  

Позволю себе сделать небольшое отступление, перед тем, как привести исходный код метода Invoke. Дело в том, что IDispatch представляет из себя только диспетчер, который вызывает нужную процедуру в зависимости от переданного DISPID, поэтому нам нужно написать код, устанавливающий текст в EditBox’е (правда, текст этот надо сначала привести в божеский вид):

Код (Text):
  1.  
  2. proc SetText, pNewText
  3.         enter
  4.         pushad
  5.         mov ebx, [pNewText]
  6.  
  7.         ;определим необходимое кол-во памяти.
  8.         invoke WideCharToMultiByte, CP_ACP, 0, ebx, -1, 0, 0, 0, 0
  9.  
  10.         push MEM_DECOMMIT
  11.         push eax
  12.  
  13.         invoke VirtualAlloc, 0, eax, MEM_COMMIT, PAGE_READWRITE
  14.  
  15.         pop ecx
  16.         push ecx
  17.         push eax
  18.  
  19.         invoke WideCharToMultiByte, CP_ACP, 0, ebx, -1, eax, ecx, 0, 0
  20.  
  21.         invoke GetDlgItem, [hWnd], 1002
  22.         mov ecx, [esp]
  23.         invoke SetWindowTextA, eax, ecx
  24.  
  25.         invoke VirtualFree
  26.  
  27.         popad
  28.         mov eax, S_OK
  29.         return
  30.  

Теперь займемся самим методом IDispatch::Invoke

HRESULT Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr);

dispIdMember – вызываемый ID (в нашем случае 1).

riid - Reserved. Должен быть IID_NULL.

wFlags может принимать значения:

  • DISPATCH_METHOD
  • DISPATCH_PROPERTYGET
  • DISPATCH_PROPERTYPUT (в нашем случае будет именно это значение)

pDispParams – указатель на структуру DISPPARAMS, через которую передаются параметры.

Код (Text):
  1.  
  2. typedef struct FARSTRUCT tagDISPPARAMS{
  3. VARIANTARG FAR* rgvarg;
  4.    DISPID FAR* rgdispidNamedArgs;
  5.    Unsigned int cArgs;
  6.    Unsigned int cNamedArgs;
  7. } DISPPARAMS;
  8.  

Так как параметр нам передается всего один (строка), то достаточно разобрать только rgvarg. Единственная проблема – элемент этого массива – указатель не на саму строку, а на структуру VARIANTARG:

Код (Text):
  1.  
  2. typedef struct FARSTRUCT tagVARIANT VARIANTARG;
  3.  
  4. typedef struct tagVARIANT  {
  5.    VARTYPE vt;
  6.    unsigned short wReserved1;
  7.    unsigned short wReserved2;
  8.    unsigned short wReserved3;
  9.    union {
  10.       Byte          bVal;           // VT_UI1.
  11.       Short         iVal;           // VT_I2.
  12.       long          lVal;           // VT_I4.
  13.       float         fltVal;         // VT_R4.
  14.       double            dblVal;         // VT_R8.
  15.       VARIANT_BOOL      boolVal;        // VT_BOOL.
  16.       SCODE         scode;          // VT_ERROR.
  17.       CY            cyVal;          // VT_CY.
  18.       DATE          date;           // VT_DATE.
  19.       BSTR          bstrVal;        // VT_BSTR.
  20.       DECIMAL           FAR* pdecVal;       //VT_BYREF|VT_DECIMAL.
  21.       IUnknown          FAR* punkVal;       // VT_UNKNOWN.
  22.       IDispatch         FAR* pdispVal;      //VT_DISPATCH.
  23.       SAFEARRAY         FAR* parray;        // VT_ARRAY|*.
  24.       Byte          FAR* pbVal;     //VT_BYREF|VT_UI1.
  25.       short         FAR* piVal;     //VT_BYREF|VT_I2.
  26.       long          FAR* plVal;     //VT_BYREF|VT_I4.
  27.       float         FAR* pfltVal;       //VT_BYREF|VT_R4.
  28.       double            FAR* pdblVal;       //VT_BYREF|VT_R8.
  29.       VARIANT_BOOL      FAR* pboolVal;      //VT_BYREF|VT_BOOL.
  30.       SCODE         FAR* pscode;        //VT_BYREF|VT_ERROR.
  31.       CY            FAR* pcyVal;        //VT_BYREF|VT_CY.
  32.       DATE          FAR* pdate;     //VT_BYREF|VT_DATE.
  33.       BSTR          FAR* pbstrVal;      //VT_BYREF|VT_BSTR.
  34.       IUnknown          FAR* FAR* ppunkVal; //VT_BYREF|VT_UNKNOWN.
  35.       IDispatch         FAR* FAR* ppdispVal;    //VT_BYREF|VT_DISPATCH.
  36.       SAFEARRAY         FAR* FAR* pparray;  // VT_ARRAY|*.
  37.       VARIANT           FAR* pvarVal;       //VT_BYREF|VT_VARIANT.
  38.       void          FAR* byref;     // GenericByRef.
  39.       char          cVal;           // VT_I1.
  40.       unsigned short        uiVal;          // VT_UI2.
  41.       unsigned long     ulVal;          // VT_UI4.
  42.       int           intVal;         // VT_INT.
  43.       unsigned int      uintVal;        // VT_UINT.
  44.       char FAR *        pcVal;          //VT_BYREF|VT_I1.
  45.       unsigned short FAR *  puiVal;         //VT_BYREF|VT_UI2.
  46.       unsigned long FAR *   pulVal;         //VT_BYREF|VT_UI4.
  47.       int FAR *         pintVal;        //VT_BYREF|VT_INT.
  48.       unsigned int FAR *    puintVal;       //VT_BYREF|VT_UINT.
  49.    };
  50. };
  51.  

Как видите, сам указатель находится по смещению +08 от начала структуры.

Вот теперь можно привести код Invoke:

Код (Text):
  1.  
  2. proc IDispatch_Invoke, pi, dispIdMember, riid, lcid, wFlags, pDispParams, \
  3.                     pVarResult, pExcepInfo, puArgErr
  4.     enter
  5.  
  6.     mov eax, [dispIdMember]
  7.     dec eax
  8.     jnz IDispatch_Invoke.notfound
  9.  
  10.     mov edx, [pDispParams]
  11.     mov edx, [edx]
  12.     mov edx, [edx + 8]
  13.  
  14.     push edx
  15.     call SetText
  16.  
  17.     mov eax, S_OK
  18.     return
  19.  
  20. .notfound:
  21.     mov eax, DISP_E_MEMBERNOTFOUND
  22.     return
  23.  

Код приложения

Код (Text):
  1.  
  2. ;---------------------------------------------------------------------
  3. ; RunScript.asm
  4. ;---------------------------------------------------------------------
  5.  
  6. format PE GUI 4.0
  7. entry start
  8.  
  9. include 'RunScript.inc'
  10.  
  11. section '.scrpt' code readable executable
  12.  
  13. start:          invoke  GetModuleHandleA, 0
  14.         mov [hInst], eax
  15.         invoke  DialogBoxParamA, eax, 1000, HWND_DESKTOP, DlgProc, 0
  16.         invoke  ExitProcess, 0
  17.  
  18.                
  19. proc DlgProc, hwnd, msg, wparam, lparam
  20.         enter
  21.         cmp [msg], WM_INITDIALOG
  22.         jz wminitdialog
  23.  
  24.         cmp [msg], WM_COMMAND
  25.         jz wmcommand
  26.  
  27.         cmp [msg], WM_CLOSE
  28.         jz wmclose
  29.  
  30.         sub eax, eax
  31.         jmp finish
  32.                
  33. wminitdialog:   mov eax, [hwnd]
  34.         mov [hWnd], eax
  35.                
  36.         invoke VirtualAlloc, 0, MAX_PATH, MEM_COMMIT, PAGE_READWRITE
  37.         mov [szFileName], eax
  38.  
  39.         call StartScriptEngine
  40.  
  41.         jmp processed
  42.                
  43. wmcommand:  cmp [wparam], BN_CLICKED shl 16 + 1001
  44.         jnz processed
  45.                  
  46.         mov eax, [szFileName]
  47.         mov ecx, 257
  48. @@:     mov byte [eax], 0
  49.         inc eax
  50.         dec ecx
  51.         jnz @B
  52.                
  53.         push szFilter
  54.         push szTitle
  55.         push dword [hwnd]
  56.         call GetFileName
  57.                
  58.         mov ecx, [szFileName]
  59.         mov ecx, [ecx]
  60.         jecxz processed
  61.                
  62.         call LoadScript
  63.         test eax, eax
  64.         jz processed
  65.                
  66.         push eax
  67.         call RunScript
  68.                
  69.         jmp processed
  70.  
  71. wmclose:    invoke VirtualFree, [szFileName], MAX_PATH, MEM_DECOMMIT
  72.            
  73.         mov edx, [pIActiveScript]
  74.                 push edx
  75.         mov edx, [edx]
  76.                 call dword [edx + Close]
  77.                
  78.                 mov edx, [pIActiveScriptParse]
  79.                 push edx
  80.         mov edx, [edx]
  81.                 call dword [edx + Release]
  82.                
  83.         mov edx, [pIActiveScript]
  84.                 push edx
  85.         mov edx, [edx]
  86.         push [pIActiveScript]
  87.                 call dword [edx + Release]
  88.                
  89.         mov edx, [pIActiveScriptSite]
  90.                 push edx
  91.         mov edx, [edx]
  92.                 call dword [edx + Release]
  93.                
  94.                 invoke  EndDialog, [hwnd], 0
  95.                
  96. processed:  sub eax, eax
  97.         inc eax
  98.        
  99. finish:     return
  100.      
  101. proc StartScriptEngine
  102.        
  103.         enter            
  104.            
  105.                 invoke CoInitialize, 0
  106.                
  107.                 invoke CoCreateInstance, CLSID_VBScript, 0, CLSCTX_INPROC_SERVER, \
  108.                         IID_IActiveScript, pIActiveScript
  109.                 test eax, eax
  110.                 js error.create_instance
  111.            
  112.                 invoke LocalAlloc, LMEM_FIXED, 16
  113.                 test eax, eax
  114.                 jz error.alloc
  115.                
  116.                 mov [ActiveScriptSiteObject], eax
  117.            
  118.                 mov dword [eax], IActiveScriptSite
  119.                 mov dword [eax + 04], IActiveScriptSiteWindow
  120.                 mov dword [eax + 08], IDispatch
  121.         mov dword [eax + 12], 1
  122.  
  123.                 mov edx, [pIActiveScript]
  124.                 mov edx, [edx]
  125.                 push pIActiveScriptParse
  126.                 push IID_IActiveScriptParse
  127.                 push [pIActiveScript]
  128.                 call dword [edx + QueryInterface]
  129.                 test eax, eax
  130.                 js .ok
  131.            
  132.                 mov edx, IActiveScriptSite
  133.         mov [pIActiveScriptSite], edx
  134.        
  135. .ok:            sub eax, eax
  136.                 return
  137.  
  138. error:
  139.  
  140. .alloc:     mov eax, E_OUTOFMEMORY
  141.         return
  142.  
  143. .create_instance:
  144.            
  145.                 sub eax, eax
  146.                 dec eax
  147.                 return
  148.  
  149. proc LoadScript
  150.         enter
  151.                
  152.         invoke CreateFileA, [szFileName], GENERIC_READ, FILE_SHARE_READ, NULL, \
  153.                         OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL
  154.         test eax, eax
  155.         jz LoadScript.finish
  156.                
  157.         mov [hFile], eax
  158.                
  159.         invoke GetFileSize, eax, 0
  160.        
  161.         mov [FileSize], eax
  162.  
  163.         mov ecx, eax
  164.         inc eax
  165.         inc eax
  166.         shl eax, 1
  167.         push eax
  168.         add eax, ecx
  169.         mov [buffer_size], eax
  170.        
  171.         invoke VirtualAlloc, 0, eax, MEM_COMMIT, PAGE_READWRITE
  172.         mov [pMemory], eax
  173.        
  174.         add eax, dword [FileSize]
  175.         inc eax
  176.         mov [pScript], eax
  177.        
  178.         push eax
  179.         lea ecx, [esp]
  180.         invoke ReadFile, [hFile], [pMemory], [FileSize], ecx, NULL
  181.         pop ecx
  182.                
  183.         invoke CloseHandle, [hFile]
  184.                
  185.         pop eax
  186.  
  187.         invoke MultiByteToWideChar, 0, 0, [pMemory], -1, [pScript], eax
  188.            
  189.             mov eax, [pScript]
  190.  
  191. .finish:    return
  192.                
  193. proc RunScript, lpScript
  194.                
  195.         enter
  196.            
  197.         mov edx, [pIActiveScriptSite]
  198.                 mov edx, [edx]
  199.                 push [pIActiveScriptSite]
  200.                 call dword [edx + Addref]
  201.                
  202.                 mov edx, [pIActiveScript]
  203.                 mov edx, [edx]
  204.             push [pIActiveScriptSite]
  205.                 push [pIActiveScript]
  206.                 call dword [edx + SetScriptSite]
  207.                
  208.                 mov edx, [pIActiveScriptParse]
  209.                 mov edx, [edx]
  210.                 push [pIActiveScriptParse]
  211.                 call dword [edx + InitNew]
  212.            
  213.                 mov edx, [pIActiveScript]
  214.                 mov edx, [edx]
  215.                 push SCRIPTITEM_ISVISIBLE
  216.                 push Item_name
  217.                 push [pIActiveScript]
  218.                 call dword [edx + AddNamedItem]
  219.  
  220.             mov edx, [pIActiveScriptParse]
  221.             mov edx, [edx]
  222.                 mov eax, [lpScript]
  223.                 sub ecx, ecx
  224.         push ecx
  225.                 push ecx
  226.         push ecx
  227.                 push ecx
  228.         push ecx
  229.                 push ecx
  230.         push ecx
  231.             push ecx
  232.         push eax
  233.         push [pIActiveScriptParse]
  234.         call dword [edx + ParseScriptText]
  235.                
  236.         mov edx, [pIActiveScript]
  237.                 mov edx, [edx]
  238.         push SCRIPTSTATE_CONNECTED
  239.         push [pIActiveScript]
  240.             call dword [edx + SetScriptState]
  241.            
  242.         invoke VirtualFree, [pMemory], [buffer_size], MEM_DECOMMIT
  243.  
  244.         return
  245.  
  246. proc IActiveScriptSite_GetLCID, pi, plcid        
  247.                 enter
  248.                 mov eax, E_NOTIMPL
  249.                 return
  250.  
  251.  
  252. proc IActiveScriptSite_GetItemInfo, pi, pstrName, dwReturnMask, ppunkItem, ppTypeInfo
  253.                 enter
  254.                 invoke lstrcmpW, [pstrName], Item_name
  255.         test eax, eax
  256.         jz @F
  257.                
  258.         mov eax, TYPE_E_ELEMENTNOTFOUND
  259.         return
  260.                
  261. @@:     mov eax, [dwReturnMask]
  262.                
  263.         cmp eax, SCRIPTINFO_IUNKNOWN
  264.         jz .IUnknown
  265.                
  266.         cmp eax, SCRIPTINFO_ALL_FLAGS
  267.         jz .IUnknown
  268.                
  269.         cmp eax, SCRIPTINFO_ITYPEINFO
  270.         jz .ITypeInfo
  271.        
  272.         mov eax, E_INVALIDARG
  273.         return     
  274.                
  275. .IUnknown:  mov eax, [ppunkItem]
  276.         mov edx, IDispatch
  277.         mov [eax], edx
  278.                
  279.         mov edx, [edx]
  280.         push IDispatch
  281.         call dword [edx + Addref]
  282.                
  283. .ITypeInfo: mov eax, [ppTypeInfo]
  284.         test eax, eax
  285.         jz @F
  286.                
  287.         and dword [eax], 0     
  288.                
  289. @@:     mov eax, S_OK
  290.         return
  291.  
  292.                            
  293. proc IActiveScriptSite_GetDocVersionString, pi, pbstrVersionString
  294.                 enter
  295.                 mov eax, E_NOTIMPL
  296.                 return                
  297.  
  298.  
  299. proc IActiveScriptSite_OnScriptTerminate, pi, pvarResult, pexcepinfo
  300.                 enter
  301.                 mov eax, S_OK
  302.                 return
  303.  
  304.  
  305. proc IActiveScriptSite_OnStateChange, pi, ssScriptState  
  306.                 enter
  307.                 mov eax, S_OK
  308.                 return
  309.  
  310.  
  311. proc IActiveScriptSite_OnScriptError, pi, pase
  312.                 enter
  313.             invoke MessageBoxA, 0, mess1, mess1_title, MB_OK + MB_ICONERROR
  314.         mov eax, S_OK
  315.                 return
  316.                
  317.                
  318. proc IActiveScriptSite_OnEnterScript, pi  
  319.                 enter
  320.                 mov eax, S_OK
  321.                 return
  322.                
  323.                
  324. proc IActiveScriptSite_OnLeaveScript, pi
  325.                 enter
  326.                 mov eax, S_OK
  327.                 return
  328.                
  329.                
  330. proc IActiveScriptSite_AddRef, pi
  331.                 enter      
  332.                 mov ecx, [ActiveScriptSiteObject]
  333.                 inc dword [ecx + 12]
  334.                 mov eax, [ecx + 12]
  335.                 return
  336.                
  337.                
  338. proc IActiveScriptSite_Release, pi
  339.                 enter
  340.                 mov ecx, [ActiveScriptSiteObject]
  341.                 dec dword [ecx + 12]
  342.                 mov eax, [ecx + 12]
  343.                 test eax, eax
  344.                 jnz @F
  345.                 invoke LocalFree, ecx
  346. @@:         return         
  347.  
  348.  
  349. proc IActiveScriptSite_QueryInterface, pi, iid, ppvObject
  350.                
  351.                 enter
  352.                 invoke IsEqualGUID, [iid], IID_IUnknown
  353.                 test eax, eax
  354.                 jnz .s_ok_unk
  355.                
  356.                 invoke IsEqualGUID, [iid], IID_IActiveScriptSite
  357.                 test eax, eax
  358.                 jnz .s_ok_unk
  359.                
  360.                 invoke IsEqualGUID, [iid], IID_IActiveScriptSiteWindow
  361.                 test eax, eax
  362.                 jnz .s_ok_acw
  363.                
  364.                 invoke IsEqualGUID, [iid], IID_IDispatch
  365.                 test eax, eax
  366.                 jnz .s_ok_dsp
  367.                
  368. .NoInterface:   mov eax, E_NOINTERFACE
  369.                 return
  370.  
  371. .s_ok:      mov edx, [pIActiveScriptSite]
  372.                 mov edx, [edx]
  373.                 push [pIActiveScriptSite]
  374.                 call dword [edx + Addref]
  375.                
  376.         mov eax, S_OK
  377.         return     
  378.  
  379. .s_ok_unk:      mov eax, [ActiveScriptSiteObject]
  380.                 mov eax, [eax]
  381.                 mov edx, [ppvObject]
  382.                 mov [edx], eax
  383.             jmp .s_ok      
  384.                
  385. .s_ok_acw:  mov eax, [ActiveScriptSiteObject]
  386.                 mov eax, [eax + 4]
  387.                 mov edx, [ppvObject]
  388.                 mov [edx], eax
  389.             jmp .s_ok
  390.                
  391. .s_ok_dsp:  mov eax, [ActiveScriptSiteObject]
  392.                 mov eax, [eax + 8]
  393.                 mov edx, [ppvObject]
  394.                 mov [edx], eax
  395.             jmp .s_ok
  396.                
  397. proc IActiveScriptSiteWindow_GetWindow, pi, phwnd
  398.         enter
  399.         mov ecx, [phwnd]
  400.             mov eax, [hWnd]
  401.             mov [ecx], eax
  402.             mov eax, S_OK      
  403.             return
  404.                
  405.  
  406. proc IActiveScriptSiteWindow_EnableModeless, pi, fEnable
  407.             enter
  408.             mov eax, S_OK
  409.             return
  410.                
  411.  
  412. proc IDispatch_GetTypeInfoCount, pi, pctinfo
  413.         enter
  414.         mov eax, [pctinfo]
  415.         mov dword [eax], 0
  416.         mov eax, S_OK
  417.         return
  418.            
  419.            
  420. proc IDispatch_GetTypeInfo, pi, iTInfo, lcid, ppTInfo  
  421.         enter
  422.         mov eax, DISP_E_BADINDEX
  423.         return
  424.                        
  425. proc IDispatch_GetIDsOfNames, pi, riid, rgszNames, cNames, lcid, rgDispId  
  426.         enter
  427.            
  428.         pushad
  429.            
  430.         mov esi, [rgszNames]
  431.         mov ebx, [rgDispId]
  432.            
  433.         lodsd
  434.            
  435.         invoke lstrcmpW, eax, szSetText
  436.         test eax, eax
  437.         jnz @F
  438.            
  439.         mov dword [ebx], 1         
  440.            
  441.         popad
  442.            
  443.         mov eax, S_OK
  444.         return
  445.            
  446. @@:     or dword [ebx], -1
  447.         popad
  448.        
  449.         mov eax, DISP_E_UNKNOWNNAME
  450.         return
  451.            
  452.  
  453. proc SetText, pNewText
  454.    
  455.         enter
  456.            
  457.             pushad
  458.             mov ebx, [pNewText]
  459.            
  460.         invoke WideCharToMultiByte, CP_ACP, 0, ebx, -1, 0, 0, 0, 0
  461.            
  462.             push MEM_DECOMMIT
  463.             push eax
  464.            
  465.             invoke VirtualAlloc, 0, eax, MEM_COMMIT, PAGE_READWRITE
  466.            
  467.             pop ecx
  468.             push ecx
  469.             push eax
  470.            
  471.             invoke WideCharToMultiByte, CP_ACP, 0, ebx, -1, eax, ecx, 0, 0
  472.  
  473.             invoke GetDlgItem, [hWnd], 1002
  474.             mov ecx, [esp]
  475.             invoke SetWindowTextA, eax, ecx
  476.            
  477.             invoke VirtualFree
  478.            
  479.             popad
  480.             mov eax, S_OK
  481.             return
  482.          
  483. proc IDispatch_Invoke, pi, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, \
  484.                                 pExcepInfo, puArgErr  
  485.         enter
  486.        
  487.         mov eax, [dispIdMember]
  488.         dec eax
  489.         jnz IDispatch_Invoke.notfound
  490.        
  491.         mov edx, [pDispParams]
  492.         mov edx, [edx]
  493.         mov edx, [edx + 8]
  494.        
  495.         push edx
  496.         call SetText
  497.  
  498.         mov eax, S_OK
  499.         return
  500.  
  501. .notfound:  mov eax, DISP_E_MEMBERNOTFOUND
  502.         return
  503.        
  504.            
  505. proc GetFileName, hParent, lpTitle, lpFilter
  506.  
  507.         enter
  508.         mov eax, [hParent]
  509.             mov [ofn.hwndOwner], eax
  510.         mov eax, [hInst]
  511.         mov [ofn.hInstance], eax
  512.         mov eax, [lpFilter]
  513.             mov [ofn.lpstrFilter], eax
  514.             mov eax, [szFileName]
  515.             mov [ofn.lpstrFile], eax
  516.             mov [ofn.nMaxFile], MAX_PATH
  517.             mov eax, [lpTitle]
  518.             mov [ofn.lpstrTitle], eax
  519.             mov [ofn.Flags], OFN_EXPLORER or OFN_FILEMUSTEXIST or OFN_LONGNAMES
  520.        
  521.         invoke GetOpenFileName, ofn
  522.        
  523.         return
  524.  
  525. section '.data' data readable writeable
  526.  
  527. ofn OPENFILENAMEA
  528.  
  529. mess1       db "Cant't parse it!", 0
  530. mess1_title     db 'script engine', 0
  531.  
  532. szFilter db 'VBScripts', 0, '*.vbs', 0, \
  533.         'All files', 0, '*.*', 0, 0
  534.          
  535. szTitle     db 'Just open script-file...', 0
  536. szFileName  dd 0
  537.  
  538. hInst dd 0
  539.  
  540. ActiveScriptSiteObject  dd 0
  541. hWnd            dd 0
  542. hFile           dd 0
  543. FileSize        dd 0
  544. buffer_size     dd 0
  545. pMemory         dd 0
  546. pScript         dd 0
  547.  
  548. Item_name dw "E", "d", "i", "t", "1", 0
  549. szSetText dw "S", "e", "t", "T", "e", "x", "t", 0
  550.  
  551. pIActiveScript      dd 0      
  552. pIActiveScriptParse     dd 0      
  553. pIActiveScriptSite  dd 0      
  554.    
  555. CLSID_VBScript GUID 0b54f3741h, 5b07h, 11cfh, 0a4h, 0b0h, 0, 0aah, 0, \
  556.                     4ah, 55h, 0e8h                        
  557. IID_IActiveScript GUID 0bb1a2ae1h, 0a4f9h, 11cfh, 8fh, 20h, 0, 80h, \
  558.                        5fh, 2ch, 0d0h, 64h  
  559. IID_IActiveScriptParse GUID 0bb1a2ae2h, 0a4f9h, 11cfh, 8fh, 20h, 0, \
  560.                             80h, 5fh, 2ch, 0d0h, 64h
  561. IID_IActiveScriptSite GUID 0d57d7817h, 0e9b7h, 04a82h, 85h, 74h, 01h, \
  562.                            0d0h, 0f9h, 3dh, 61h, 70h  
  563. IID_IActiveScriptSiteWindow GUID 0d10f6761h, 083e9h, 011cfh, 8fh, 20h, \
  564.                                  0, 80h, 5fh, 2ch, 0d0h, 64h
  565. IID_IUnknown GUID 0, 0, 0, 0ch, 0, 0, 0, 0, 0, 0, 46h  
  566. IID_IDispatch GUID 00020400h, 0, 0, 0c0h, 0, 0, 0, 0, 0, 0, 46h
  567.                      
  568.  
  569. IActiveScriptSite dd IActiveScriptSite_vtable
  570. IActiveScriptSiteWindow dd IActiveScriptSiteWindow_vtable
  571. IDispatch dd IDispatch_vtable                      
  572.  
  573.  
  574. IActiveScriptSite_vtable dd IActiveScriptSite_QueryInterface
  575.                          dd IActiveScriptSite_AddRef
  576.                          dd IActiveScriptSite_Release
  577.                          dd IActiveScriptSite_GetLCID
  578.                          dd IActiveScriptSite_GetItemInfo
  579.                          dd IActiveScriptSite_GetDocVersionString
  580.                          dd IActiveScriptSite_OnScriptTerminate
  581.                          dd IActiveScriptSite_OnStateChange
  582.                          dd IActiveScriptSite_OnScriptError
  583.                          dd IActiveScriptSite_OnEnterScript
  584.                          dd IActiveScriptSite_OnLeaveScript
  585.                        
  586. IActiveScriptSiteWindow_vtable  dd IActiveScriptSite_QueryInterface
  587.                             dd IActiveScriptSite_AddRef
  588.                             dd IActiveScriptSite_Release
  589.                 dd IActiveScriptSiteWindow_GetWindow
  590.                 dd IActiveScriptSiteWindow_EnableModeless
  591.  
  592. IDispatch_vtable dd IActiveScriptSite_QueryInterface
  593.         dd IActiveScriptSite_AddRef
  594.         dd IActiveScriptSite_Release
  595.                                
  596.         dd IDispatch_GetTypeInfoCount
  597.         dd IDispatch_GetTypeInfo
  598.         dd IDispatch_GetIDsOfNames
  599.         dd IDispatch_Invoke
  600.  
  601. QueryInterface  = 0
  602. Addref          = 04h
  603. Release         = 08h                
  604. Close       = 1ch
  605. SetScriptSite   = 0ch
  606. InitNew     = 0ch
  607. ParseScriptText = 14h
  608. SetScriptState  = 14h
  609. AddNamedItem    = 20h
  610.  
  611. section '.idata' import data readable writeable
  612. library kernel32, 'kernel32.dll', \
  613.     user32, 'user32.dll', \
  614.         ole32, 'ole32.dll', \
  615.         comdlg32, 'comdlg32.dll'
  616.  
  617.        
  618. import kernel32, ExitProcess, 'ExitProcess', \
  619.          LocalAlloc, 'LocalAlloc', \
  620.              LocalFree, 'LocalFree', \
  621.              GetModuleHandleA, 'GetModuleHandleA', \
  622.              CreateFileA, 'CreateFileA', \
  623.              CloseHandle, 'CloseHandle', \
  624.          ReadFile, 'ReadFile', \
  625.              GetFileSize, 'GetFileSize', \
  626.              MultiByteToWideChar, 'MultiByteToWideChar', \
  627.              WideCharToMultiByte, 'WideCharToMultiByte', \
  628.              VirtualAlloc, 'VirtualAlloc', \
  629.              VirtualFree, 'VirtualFree', \
  630.              lstrcmpW, 'lstrcmpW'
  631.  
  632.        
  633. import ole32, CoInitialize, 'CoInitialize', \
  634.               CoCreateInstance, 'CoCreateInstance', \
  635.               IsEqualGUID, 'IsEqualGUID'
  636.  
  637. import user32, DialogBoxParamA, 'DialogBoxParamA', \
  638.            EndDialog, 'EndDialog', \
  639.            MessageBoxA, 'MessageBoxA', \
  640.            SetWindowTextA, 'SetWindowTextA', \
  641.            GetDlgItem, 'GetDlgItem'
  642.        
  643. import comdlg32, GetOpenFileName, 'GetOpenFileNameA'
  644.  
  645. section '.rsrc' resource data readable
  646.  
  647. directory RT_DIALOG, dialogs
  648.  
  649. resource dialogs, 1000, LANG_ENGLISH+SUBLANG_DEFAULT, main_dlg
  650.  
  651. dialog main_dlg, 'RunScript', 70, 70, 170, 70, \
  652.        WS_CAPTION + WS_POPUP + WS_SYSMENU + DS_MODALFRAME
  653.  
  654. dialogitem 'BUTTON', 'Execute Script!', 1001, 52, 35, 55, 15, \
  655.            WS_VISIBLE + WS_TABSTOP + BS_PUSHBUTTON
  656. dialogitem 'EDIT', '', 1002, 10, 15, 150, 15, WS_VISIBLE + WS_BORDER + WS_TABSTOP
  657.  
  658. enddialog
  659.  
  660.  
  661. ;---------------------------------------------------------------------
  662. ; RunScript.inc
  663. ;---------------------------------------------------------------------
  664.  
  665. include 'include\win32ax.inc'
  666.  
  667. CLSCTX_INPROC_SERVER        equ 1
  668. CLSCTX_INPROC_HANDLER       equ 2
  669. CLSCTX_LOCAL_SERVER     equ 4
  670. CLSCTX_INPROC_SERVER16      equ 8
  671. CLSCTX_REMOTE_SERVER        equ 10h
  672. CLSCTX_INPROC_HANDLER16     equ 20h
  673. CLSCTX_INPROC_SERVERX86     equ 40h
  674. CLSCTX_INPROC_HANDLERX86    equ 80h
  675. CLSCTX_ESERVER_HANDLER      equ 100h
  676.  
  677. E_NOTIMPL       equ 80004001h
  678. E_NOINTERFACE       equ 80004002h
  679. E_INVALIDARG        equ 80070057h
  680.  
  681. TYPE_E_ELEMENTNOTFOUND      equ 8002802Bh
  682.  
  683. S_OK                            equ 0
  684.  
  685. LMEM_FIXED                  equ 0h
  686.  
  687. E_OUTOFMEMORY                   equ 8007000Eh
  688.  
  689. SCRIPTSTATE_UNINITIALIZED   equ 0h
  690. SCRIPTSTATE_STARTED         equ 1h
  691. SCRIPTSTATE_CONNECTED           equ 2h
  692. SCRIPTSTATE_DISCONNECTED    equ 3h
  693. SCRIPTSTATE_CLOSED          equ 4h
  694. SCRIPTSTATE_INITIALIZED     equ 5h
  695.  
  696. CP_ACP              equ 0
  697.  
  698. SCRIPTITEM_ISVISIBLE        equ 000000002h
  699. SCRIPTITEM_ISSOURCE     equ 000000004h
  700. SCRIPTITEM_GLOBALMEMBERS    equ 000000008h
  701. SCRIPTITEM_ISPERSISTENT     equ 000000040h
  702. SCRIPTITEM_CODEONLY     equ 000000200h
  703. SCRIPTITEM_NOCODE       equ 000000400h
  704. SCRIPTITEM_ALL_FLAGS        equ 00000064eh
  705.  
  706. SCRIPTINFO_IUNKNOWN     equ 000000001h
  707. SCRIPTINFO_ITYPEINFO        equ 000000002h
  708. SCRIPTINFO_ALL_FLAGS        equ 000000003h
  709.  
  710. CC_STDCALL      equ     4h
  711.  
  712. DISPATCH_METHOD     equ 1
  713. DISPATCH_PROPERTYGET    equ 2
  714. DISPATCH_PROPERTYPUT    equ 4
  715. DISPATCH_PROPERTYPUTREF equ 8
  716. DISP_E_BADINDEX     equ     8002000Bh
  717. DISP_E_MEMBERNOTFOUND   equ     80020003h
  718. DISP_E_UNKNOWNNAME  equ     80020006h
  719.  
  720. VT_EMPTY            equ 0
  721. VT_NULL             equ 1
  722. VT_I2               equ 2
  723. VT_I4               equ 3
  724. VT_R4               equ 4
  725. VT_R8               equ 5
  726. VT_CY               equ 6
  727. VT_DATE             equ 7
  728. VT_BSTR             equ 8
  729. VT_DISPATCH         equ 9
  730. VT_ERROR            equ 10
  731. VT_BOOL             equ 11
  732. VT_VARIANT          equ 12
  733. VT_UNKNOWN          equ 13
  734. VT_DECIMAL          equ 14
  735. VT_I1               equ 16
  736. VT_UI1              equ 17
  737. VT_UI2              equ 18
  738. VT_UI4              equ 19
  739. VT_I8               equ 20
  740. VT_UI8              equ 21
  741. VT_INT              equ 22
  742. VT_UINT             equ 23
  743. VT_VOID             equ 24
  744. VT_HRESULT          equ 25
  745. VT_PTR              equ 26
  746. VT_SAFEARRAY        equ 27
  747. VT_CARRAY           equ 28
  748. VT_USERDEFINED      equ 29
  749. VT_LPSTR            equ 30
  750. VT_LPWSTR           equ 31
  751. VT_RECORD           equ 36
  752. VT_FILETIME         equ 64
  753. VT_BLOB             equ 65
  754. VT_STREAM           equ 66
  755. VT_STORAGE          equ 67
  756. VT_STREAMED_OBJECT  equ 68
  757. VT_STORED_OBJECT    equ 69
  758. VT_BLOB_OBJECT      equ 70
  759. VT_CF               equ 71
  760. VT_CLSID            equ 72
  761. VT_BSTR_BLOB        equ 0fffh
  762. VT_VECTOR           equ 1000h
  763. VT_ARRAY            equ 2000h
  764. VT_BYREF            equ 4000h
  765. VT_RESERVED         equ 8000h
  766. VT_ILLEGAL          equ 0ffffh
  767. VT_ILLEGALMASKED    equ 0fffh
  768. VT_TYPEMASK         equ 0fffh
  769.  
  770. struc GUID dd1, dw1, dw2, db1, db2, db3, db4, db5, db6, db7, db8
  771. {
  772. .dd1 dd dd1
  773. .dw1 dw dw1
  774. .dw2 dw dw2
  775. .db1 db db1
  776. .db2 db db2
  777. .db3 db db3
  778. .db4 db db4
  779. .db5 db db5
  780. .db6 db db6
  781. .db7 db db7
  782. .db8 db db8
  783. }
  784.  
  785. MAX_PATH equ 260
  786.  
  787. struc OPENFILENAMEA
  788. {
  789. .lStructSize        dd 4ch
  790. .hwndOwner          dd 0
  791. .hInstance          dd 0
  792. .lpstrFilter        dd 0
  793. .lpstrCustomFilter  dd 0
  794. .nMaxCustFilter     dd 0
  795. .nFilterIndex       dd 0
  796. .lpstrFile          dd 0
  797. .nMaxFile           dd 0
  798. .lpstrFileTitle     dd 0
  799. .nMaxFileTitle      dd 0
  800. .lpstrInitialDir    dd 0
  801. .lpstrTitle         dd 0
  802. .Flags              dd 0
  803. .nFileOffset        dw 0
  804. .nFileExtension     dw 0
  805. .lpstrDefExt        dd 0
  806. .lCustData          dd 0
  807. .lpfnHook           dd 0
  808. .lpTemplateName     dd 0
  809. }
  810. struct OPENFILENAMEA
  811.  

Продолжение ожидается...

Файл к статье © Hangatyr


0 1.402
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532