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

Дата публикации 3 янв 2004

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

Предисловие

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

Пара слов о компиляторе

Я не буду здесь поднимать бесполезный вопрос о том какой компилятор самый лучше и т.п. - в конце концов это дело вкуса. Скажу только, что я буду использовать fasm (http://flatassembler.net) и, соответственно, полагаю, что для читателя не будет сюрпризом увидеть

Код (Text):
  1.  
  2. add eax, dword [ecx]

вместо

Код (Text):
  1.  
  2. add eax, dword ptr [ecx]

Но вообще-то это, наверное, не проблема ;)

Colib

Говоря о использовании COM в ассемблере нельзя не сказать о работах Ernest Murphy, в том числе о библиотеке Colib, которая предоставляет нам набор удобных функций для работы с COM-объектами. Но у нее есть один минус - она ориентирована на MASM. Хотя минус это или плюс решать не мне и если ваш любимый ассемблер - MASM32 (с которым, кстати, и поставляется вышеозначенная библиотека), то вы вполне можете радоваться, т.к. часть работы уже сделана за вас. Но изучить прилагающиеся к ней примеры не помешает в любом случае. Еще советую почитать статью "Using COM in Assembly Language" by Bill Tyler.

Основы Component Object Model

В этом разделе я постараюсь кратко объяснить некоторые основы технологии COM, которые необходимы для понимания материала, изложенного в данной статье. Как обычно, те кто уже имеет нужные знания (а нужно нам не так уж и много) могут спокойно пропустить этот раздел и перейти сразу ко второй части. А для оставшихся продолжаем.

Введение

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

Что же такое COM? Не более, чем набор правил, определяющих каким образом могут взаимодействовать компоненты, написанные в общем случае разными людьми и на разных языках программирования, это стандарт, призванный обеспечить возможность их совместной работы. Идея, лежащая в основе, довольно проста - код, который должен стать всеобщим достоянием оформляется в виде своеобразного мини-приложения, так называемого COM-объекта. А функции, которые должны быть доступны извне группируются в интерфейсы этого объекта. Через них и осуществляется взаимодействие с клиентами. Интерфейсов может быть сколько угодно - правило здесь только одно - спецификация COM требует, чтобы каждый объект содержал специальный интерфейс IUnknown, а также чтобы любой другой интерфейс так или иначе наследовался от него.

Интерфейс IUnknown

Этот интерфейс занимает в COM особое место и это не случайно - с его помощью можно всегда получить остальные интерфейсы, поддерживающиеся объектом, кроме этого он предоставляет нам некоторые базовые средства управления жизнью объекта. Вот 3 его метода (функции интерфейсов называются методами):

HRESULT QueryInterface(REFIID iid, void **ppvObject) - данный метод используется для получение указателя на интерфейс объекта по идентификатору. Если запрошенный интерфейс поддерживается объектом, то будет возвращено значение S_OK и указатель на интерфейс помещен в ppvObject. В противном случае возвращается E_NOINTERFACE.

ULONG AddRef(void) - инкрементирует счетчик использования объекта и должен вызываться всякий раз, когда некто собирается использовать объект (например, он должен вызывается всякий раз, когда метод QueryInterface возвращает указаетель на какой-нибудь интерфейс объекта). Возвращаемое значение - новое значение счетчика ссылок.

ULONG Release(void) - этот метод выполняет обратные действия и должен вызываться, когда клиент закончил работу с объектом.

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

Структура объектов и интерфейсов

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

А вот интерфейсы в отличии от объектов должны иметь четко оговоренную структуру.

Основой интерфейса является массив адресов функций (часто называемый просто "vtable"). В качестве примера рассмотрим простейший интерфейс, состоящий из четырех методов (три из них - методы IUnknown).

Код (Text):
  1.  
  2. ...
  3. proc Addref, pi
  4. enter
  5. ...
  6. return
  7. ...
  8.  
  9. proc Method1, pi
  10. enter
  11. ...
  12. return
  13. ...
  14.  
  15. IsomeInterface      dd  IsomeInterface_vtable
  16.  
  17. IsomeInterface_vtable   dd  QueryInterface
  18.                 dd  Addref
  19.                 dd  Release
  20.                 dd  Method1

Довольно просто, не так ли? Чтобы вызвать определенный метод нужно знать только его положение в vtable, правда тут есть одна тонкость - первым параметром методу всегда передается указатель на интерфейс - даже если в описании метода значится void т.е. вызов Release будет выглядеть не так:

Код (Text):
  1.  
  2. mov eax, [IsomeInterface]
  3.             call dword [eax + 8]

а вот так:

Код (Text):
  1.  
  2.             mov eax, [IsomeInterface]
  3.             push Isome_interface
  4.             call dword [eax + 8]

Дело в том, что описания методов даются, как правило, для языков высокого уровня, а там эту работу за нас выполняет компилятор и, например, на C аналогичный вызов действительно будет таким:

Код (Text):
  1.  
  2.             pIUnknown->Release();

Script Engines.

Предположим, что у нас в наличии есть такая программка:

(Легко заметить, что она ничего не делает кроме того, что показывает окно открытия файла по нажатию на кнопку)

Код (Text):
  1.  
  2. format PE GUI 4.0
  3. entry start
  4. include 'include\win32ax.inc'
  5. section '.scrpt' code readable executable
  6.  
  7. start:      invoke GetModuleHandleA, 0
  8.         mov [hInst], eax
  9.         invoke DialogBoxParamA, eax, 1000, HWND_DESKTOP, DlgProc, 0
  10.         invoke ExitProcess, 0
  11.  
  12. proc DlgProc, hwnd, msg, wparam, lparam
  13.         enter
  14.         cmp [msg], WM_INITDIALOG
  15.         jz wminitdialog
  16.         cmp [msg], WM_COMMAND
  17.         jz wmcommand
  18.         cmp [msg], WM_CLOSE
  19.         jz wmclose
  20.         sub eax, eax
  21.         jmp finish
  22.                
  23. wminitdialog:
  24. mov eax, [hwnd]
  25.         mov [hWnd], eax
  26.         invoke VirtualAlloc, 0, MAX_PATH, MEM_COMMIT, PAGE_READWRITE
  27.         mov [szFileName], eax
  28.        
  29.         jmp processed
  30.                
  31. wmcommand:  cmp [wparam], BN_CLICKED shl 16 + 1001
  32.         jnz processed
  33.  
  34.         mov eax, [szFileName]
  35.         mov ecx, MAX_PATH
  36. @@:     mov byte [eax], 0
  37.         inc eax
  38.         dec ecx
  39.         jnz @B
  40.                
  41.         push szFilter
  42.         push szTitle
  43.         push dword [hwnd]
  44.         call GetFileName
  45.                
  46.         jmp processed
  47.  
  48. wmclose:    invoke VirtualFree, [szFileName], MAX_PATH, MEM_DECOMMIT
  49.             invoke EndDialog, [hwnd], 0
  50.                
  51. processed:  sub eax, eax
  52.         inc eax
  53.        
  54. finish: return
  55.      
  56. proc GetFileName, hParent, lpTitle, lpFilter
  57.  
  58.         enter
  59.         mov eax, [hParent]
  60.             mov [ofn.hwndOwner], eax
  61.         mov eax, [hInst]
  62.         mov [ofn.hInstance], eax
  63.         mov eax, [lpFilter]
  64.             mov [ofn.lpstrFilter], eax
  65.             mov eax, [szFileName]
  66.             mov [ofn.lpstrFile], eax
  67.             mov [ofn.nMaxFile], MAX_PATH
  68. mov eax, [lpTitle]
  69.             mov [ofn.lpstrTitle], eax
  70.             mov [ofn.Flags], OFN_EXPLORER or OFN_FILEMUSTEXIST or OFN_LONGNAMES
  71.        
  72.         invoke GetOpenFileName, ofn
  73.         return
  74.  
  75. section '.data' data readable writeable
  76.  
  77. ofn OPENFILENAMEA
  78.  
  79. szFilter db 'VBScripts', 0, '*.vbs', 0, \
  80.         'All files (heh... you can try...)', 0, '*.*',  0, 0
  81.          
  82. szTitle db 'Just open file...', 0
  83. szFileName dd 0
  84. hInst dd 0
  85. hWnd dd 0
  86. section '.idata' import data readable writeable
  87. library kernel32, 'kernel32.dll', \
  88.     user32, 'user32.dll', \
  89.        comdlg32, 'comdlg32.dll'
  90.        
  91. import kernel32, ExitProcess, 'ExitProcess', \
  92.          VirtualAlloc, 'VirtualAlloc', \
  93.              VirtualFree, 'VirtualFree', \
  94.         GetModuleHandleA, 'GetModuleHandleA'
  95.        
  96. import user32, DialogBoxParamA, 'DialogBoxParamA', \
  97.            EndDialog, 'EndDialog', \
  98.            MessageBoxA, 'MessageBoxA'
  99.        
  100. import comdlg32, GetOpenFileName, 'GetOpenFileNameA'       
  101.  
  102. section '.rsrc' resource data readable
  103.  
  104. directory RT_DIALOG, dialogs
  105.  
  106. resource dialogs, 1000, LANG_ENGLISH+SUBLANG_DEFAULT, main_dlg
  107.  
  108. dialog main_dlg, 'RunScript', 70, 70, 70, 50, WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
  109.   dialogitem 'BUTTON', 'Execute Script!', 1001, 8, 15, 55, 15, WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON
  110. enddialog

А также имеется скрипт:

Код (Text):
  1.  
  2. Dim a, b
  3. a = InputBox("A:")
  4. b = MsgBox("A^2=" & a^2, 64, "--")

(Да простят меня Боги за появление здесь этих крамольных строк ;)

И кроме этого есть еще желание заставить его выполнятся. Ну что же приступим...

На сегодняшний день всеми нами любимая корпорация Microsoft предоставляет скиптовые движки JavaScript и VBScript совершенно свободно - единственное, чего они хотят, так это упоминание о них в AboutBox'e программы, что, согласитесь, довольно нетипично.

Физически эти движки находятся в файлах jscript.dll и vbscript.dll, но оформлены в виде COM-объектов, а значит наша цель - написать приложение, которое может работать с COM, чем мы сейчас и займемся.

Самое первое, что нужно сделать - это поставить вызов функции CoInitialize где-нибудь в начале, например, при создании окна:

Код (Text):
  1.  
  2. wminitdialog:   mov eax, [hwnd]
  3.             mov [hWnd], eax
  4.             invoke CoInitialize, 0

Данная функция инициализирует библиотеку COM и должна быть вызвана перед использованием любых CoXXX-функций.

Теперь с помощью API CoCreateInstance попросим систему создать для нас объект, который предоставит интерфейсы для управления движком VBScript.

Код (Text):
  1.  
  2.     invoke CoCreateInstance, CLSID_VBScript, 0, CLSCTX_INPROC_SERVER, \
  3.            IID_IActiveScript, pIActiveScript

Первый параметр представляет собой идентификатор класса, к которому принадлежит создаваемый объект. Нужный нам объект принадлежит к классу "VB Script Language", имеющему ID 0b54f3741h-5b07h-11cfh-0a4b0h-00aa004a55e8h

Второй параметр указывает где должен быть запущен код, создающий объект. Значение CLSCTX_INPROC_SERVER говорит, чтобы это было сделано в контексте нашего процесса.

Третий представляет собой идентификатор запрашиваемого интерфейса. В нашем случае он должен быть таким: 0bb1a2ae1h-0a4f9h-11cfh-8fh20h-0805f2c0d064

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

IActiveScript - содержит методы для инициализации движка и управления его состоянием. А с помощью IActiveScriptParse мы можем указать скрипт, который нужно выполнить.

В случае успешного заверешения вызова CoCreateInstance в pIActiveScript будет помещен указатель на интерфейс IActiveScript, который мы запросили, указав GUID 0bb1a2ae1h-0a4f9h-11cfh-8fh20h-0805f2c0d064.

Но нам нужен еще и интерфейс IActiveScriptParse, давайте его сейчас получим. Так как он является интерфесом того же объекта, что и IActiveScript мы можем воспользоваться методом QueryInterface последнего.

Код (Text):
  1.  
  2.         mov edx, [pIActiveScript]
  3.         mov edx, [edx]
  4.         push pIActiveScriptParse
  5.         push IID_IActiveScriptParse
  6.         push [pIActiveScript]
  7.         call dword [edx]

Этот код поместит указатель на IActiveScriptParse в переменную pIActiveScriptParse.

Теперь у нас есть все, чтобы управлять скриптовым движком. Думаете это все? Самое интересное еще впереди ;)

IActiveScriptSite и IActiveScriptSiteWindow.

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

Надеюсь, ни для кого не станет сюрпризом, что это "средство связи" является ничем иным, как еще одним объектом ;) Стало быть, настало применить на практике все теоритические знания о COM, потому что нам предстоит создать этот объект и реализовать все методы его интерфейсов. Интерфейсов будет два - IActiveScriptSite и IActiveScriptSiteWindow.

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

  • QueryInterface
  • AddRef
  • Release
  • GetLCID
  • GetItemInfo
  • GetDocVersionString
  • OnScriptTerminate
  • OnStateChange
  • OnScriptError
  • OnEnterScript
  • OnLeaveScript

А вот интерфейс IActiveScriptSiteWindow реализовывать строго говоря необязательно, но мы все же это сделаем. И вот почему - когда скрипт захочет как-нибудь взаимодействовать с GUI (например, отобразить обычный мессадж бокс) движку потребуется хэндл окна, которому этот месседж бокс принадлежит. Что он сделает? Запросит указатель на интерфейс IActiveScriptSiteWindow и с помощью метода GetWindow получит вожделенный hWnd. Если обнаружится, что объект не поддерживает IActiveScriptSiteWindow или что-нибудь в этом роде, то движок сообщит об ошибке и прекратит выполнение скрипта. Вот именно поэтому нам нужно реализовать этот интерфейс - чтобы увидеть результаты работы.

Реализация объекта.

Как я уже говорил спецификация COM не предусматривает никаких особых стандартов реализации объектов. Мы выберем самый простой путь - наш объект будет содержать:

- указатели на интерфейсы IActiveScriptSite и IActiveScriptSiteWindow,
- счетчик ссылок (любой хороший объект должен содержать счетчик ссылок или хотя бы делать вид, что содержит ;)

Перво-наперво нужно определить, где это все будет храниться. Мы воспользуемся API LocalAlloc и выделим для него немного памяти.

Код (Text):
  1.  
  2.         invoke LocalAlloc, LMEM_FIXED, 12
  3.         mov [ActiveScriptSiteObject], eax
  4.         mov [eax + 8], 1    ;Инициализируем счетчик ссылок

Теперь у нас есть объект - дело за интерфейсами. Сперва реализуем методы IUnknown:

Код (Text):
  1.  
  2. proc IActiveScriptSite_QueryInterface, pi, iid, ppvObject
  3.        
  4.         enter
  5.                invoke IsEqualGUID, [iid], IID_IUnknown
  6.         test eax, eax
  7.         jnz .s_ok
  8.                
  9.         invoke IsEqualGUID, [iid], IID_IActiveScriptSite
  10.         test eax, eax
  11.         jnz .s_ok
  12.                
  13.         invoke IsEqualGUID, [iid], IID_IActiveScriptSiteWindow
  14.         test eax, eax
  15.         jnz .S_OK_W
  16.                
  17. .NoInterface:   mov eax, E_NOINTERFACE
  18.                
  19.                 return
  20.  
  21. .s_ok:          mov eax, [ActiveScriptSiteObject]
  22.                 mov eax, [eax]
  23.                 mov edx, [ppvObject]
  24.                 mov [edx], eax
  25.                 mov eax, S_OK
  26.                
  27.                 return      
  28.                
  29. .S_OK_W:    mov eax, [ActiveScriptSiteObject]
  30.                 mov eax, [eax + 4]
  31.                 mov edx, [ppvObject]
  32.                 mov [edx], eax
  33.                 mov eax, S_OK                          
  34.         return

Здесь мы с помощью API IsEqualGUID сверяем переданный нам GUID с эталонным и если они совпадают, то возвращаем указатель на соответствующий интерфейс. Пояснение здесь требуется только одно - так как наш объект не имеет самостоятельного IUnknown, то в ответ на идентификатор 00000000-0000-0000-0c00000000000046h (GUID IUnknown) мы вернем указатель на IActiveScriptSite, что в данном случае одно и тоже.

Код (Text):
  1.  
  2. proc IActiveScriptSite_AddRef, pi
  3.                enter      
  4.                 mov ecx, [ActiveScriptSiteObject]
  5.                 inc dword [ecx + 8]
  6.                 mov eax, [ecx + 8]
  7.                 return

Тут вообще комментариев не требуются ;)

Код (Text):
  1.  
  2. proc IActiveScriptSite_Release, pi
  3.                enter    
  4.                 mov ecx, [ActiveScriptSiteObject]
  5.                dec dword [ecx + 8]
  6.                mov eax, [ecx + 8]
  7.                test eax, eax
  8.                jnz .ret_
  9.                invoke LocalFree, ecx
  10. .ret_:          return

Наконец, последний метод - Release - он уменьшает значение счетчика до тех пор, пока оно не станет равным 0, затем память освобождается с помощью LocalFree.

Теперь остается имплементировать следующие методы:

  • GetLCID
  • GetItemInfo
  • GetDocVersionString
  • OnScriptTerminate
  • OnStateChange
  • OnScriptError
  • OnEnterScript
  • OnLeaveScript
  • GetWindow
  • EnableModeless

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

Код (Text):
  1.  
  2. proc IActiveScriptSite_OnEnterScript, pi  
  3.                 enter
  4.                 mov eax, S_OK
  5.                 return

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

Код (Text):
  1.  
  2. proc IActiveScriptSite_GetLCID, pi, plcid        
  3.                 enter
  4.                 mov eax, E_NOTIMPL
  5.                 return

На такой манер можно написать все методы IActiveScriptSite, что мы и сделаем.

Код (Text):
  1.  
  2. proc IActiveScriptSite_GetItemInfo, pi, pstrName, dwReturnMask, ppunkItem, ppTypeInfo
  3.                enter
  4.                 mov eax, TYPE_E_ELEMENTNOTFOUND
  5.         return
  6.  
  7. proc IActiveScriptSite_GetDocVersionString, pi, pbstrVersionString
  8.                 enter
  9.                mov eax, E_NOTIMPL
  10.                 return                
  11.  
  12. proc IActiveScriptSite_OnScriptTerminate, pi, pvarResult, pexcepinfo
  13.                 enter
  14.                mov eax, S_OK
  15.                return
  16.  
  17. proc IActiveScriptSite_OnStateChange, pi, ssScriptState  
  18.                enter
  19.                 mov eax, S_OK
  20.                return
  21.  
  22. proc IActiveScriptSite_OnEnterScript, pi  
  23.                enter
  24.             mov eax, S_OK
  25.                 return
  26.                
  27. proc IActiveScriptSite_OnLeaveScript, pi
  28.                 enter
  29.                 mov eax, S_OK
  30.                return

Только в метод OnScriptError (угадайте в какой ситуации он вызывается;)) мы кое-что добавим:

Код (Text):
  1.  
  2. proc IActiveScriptSite_OnScriptError, pi, pase
  3.                enter
  4.            
  5.         invoke MessageBoxA, 0, mess1, mess1_title, MB_OK + MB_ICONERROR
  6.         mov eax, S_OK
  7.                 return

Теперь при обнаружение ошибки в скрипте будет появляться окно с соответствующим сообщением.

OK, с IActiveScriptSite вроде разобрались - настала очередь IActiveScriptSiteWindow. Тут будет проще - нужно написать все два метода.

Код (Text):
  1.  
  2. proc IActiveScriptSiteWindow_GetWindow, pi, phwnd
  3.         enter
  4.         mov ecx, [phwnd]    ;Вернем hWnd нашего окна.
  5.             mov eax, [hWnd]
  6.             mov [ecx], eax
  7.             mov eax, S_OK      
  8.             return
  9.                
  10. proc IActiveScriptSiteWindow_EnableModeless, pi, fEnable
  11.             enter
  12.             mov eax, S_OK
  13.             return

Так как оба эти интерфейса принадлежат одному объекту, то пусть используют одни и те же стандартные методы. Обе Vtable разместим в сегменте данных, они будут такими:

Код (Text):
  1.  
  2. pIActiveScriptSite_vtable       dd IActiveScriptSite_vtable
  3. pIActiveScriptSiteWindow_vtable     dd IActiveScriptSiteWindow_vtable
  4.  
  5. IActiveScriptSite_vtable    dd IActiveScriptSite_QueryInterface
  6.                             dd IActiveScriptSite_AddRef
  7.                             dd IActiveScriptSite_Release
  8.                             dd IActiveScriptSite_GetLCID
  9.                             dd IActiveScriptSite_GetItemInfo
  10.                             dd IActiveScriptSite_GetDocVersionString
  11.                             dd IActiveScriptSite_OnScriptTerminate
  12.                             dd IActiveScriptSite_OnStateChange
  13.                             dd IActiveScriptSite_OnScriptError
  14.                             dd IActiveScriptSite_OnEnterScript
  15.                             dd IActiveScriptSite_OnLeaveScript
  16.                        
  17. IActiveScriptSiteWindow_vtable  dd IActiveScriptSite_QueryInterface
  18.                             dd IActiveScriptSite_AddRef
  19.                             dd IActiveScriptSite_Release
  20.                 dd IActiveScriptSiteWindow_GetWindow
  21.                 dd IActiveScriptSiteWindow_EnableModeless

Ну и напоследок поместим указатели на интерфейсы в выделенной для объекта памяти:

Код (Text):
  1.  
  2.         invoke LocalAlloc, LMEM_FIXED, 12
  3.         mov [ActiveScriptSiteObject], eax
  4.         mov [eax + 8], 1    ;Инициализируем счетчик ссылок
  5.                mov dword [eax], pIActiveScriptSite_vtable
  6.                 mov dword [eax + 4], pIActiveScriptSiteWindow_vtable

Все! Наш объект готов, методы имплементированы, осталось только подготовить и запустить скрипт.

Подготовка.

Что же скрывается за словом "подготовить"? Ну во-первых, конечно же открыть файл со скриптом (если вы помните, его имя мы получаем при помощи GetOpenFileName). Открываем как обычно, используя API CreateFile:

Код (Text):
  1.  
  2.         invoke CreateFileA, [szFileName], GENERIC_READ, FILE_SHARE_READ, \
  3.                             NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL
  4.         mov [hFile], eax

Кроме этого нам нужен его размер:

Код (Text):
  1.  
  2.         invoke GetFileSize, eax, 0
  3.         mov [FileSize], eax

Вычислим сколько памяти нужно выделить (зачем умножать на 2 объясню чуть позже):

Код (Text):
  1.  
  2.         mov ecx, eax
  3.         inc eax
  4.         inc eax
  5.         shl eax, 1
  6.         push eax
  7.         add eax, ecx
  8.         mov [buffer_size], eax

Выделяем память при помощи VirtualAlloc:

Код (Text):
  1.  
  2.         invoke VirtualAlloc, 0, eax, MEM_COMMIT, PAGE_READWRITE
  3.         mov [pMemory], eax

Первые FileSize байт будут заняты содержимым файла, остальные пока свободны:

Код (Text):
  1.    
  2.         add eax, dword [FileSize]
  3.         inc eax
  4.         mov [pScript], eax
  5.        
  6.         push eax
  7.         lea ecx, [esp]
  8.         invoke ReadFile, [hFile], [pMemory], [FileSize], ecx, NULL
  9.         pop ecx

За ненадобностью закрываем файл.

Код (Text):
  1.  
  2.         invoke CloseHandle, [hFile]
  3.                
  4.         pop eax

Вот теперь раскажу зачем была выделена дополнительная память. Дело в том, что сейчас наш скрипт в памяти представляет собой обычную ASCII-последовательность, а VBScript engine оперирует со строками в формате Wide-Character (т.е. каждый символ занимает слово, а не байт). Поэтому наш скрипт еще предстоит конвертировать, что проще всего сделать с помощью MultiByteToWideChar:

Код (Text):
  1.  
  2.     invoke MultiByteToWideChar, 0, 0, [pMemory], -1, [pScript], eax

Запуск.

В этом разделе мы рассмотрим как инициализировать движок и передать ему скрипт.

Во-первых нужно увеличить значение счетчика нашего объекта, чтобы он не уничтожился раньше времени ;)

Код (Text):
  1.  
  2.         mov edx, [pIActiveScriptSite]
  3.                 mov edx, [edx]
  4.                 push [pIActiveScriptSite]
  5.                 call dword [edx + Addref]

Далее скажем IActiveScript, что использовать в качестве IActiveScriptSite необходимо реализованный нами интерфейс, для чего используем метод SetScriptSite, передав ему соответствующий указатель:

Код (Text):
  1.  
  2.         mov edx, [pIActiveScript]
  3.                 mov edx, [edx]
  4.                 push [pIActiveScriptSite]
  5.                 push [pIActiveScript]
  6.                 call dword [edx + 0ch]

Теперь инициализируем движок с помощью метода InitNew интерфейса IActiveScriptParse:

Код (Text):
  1.  
  2.                 mov edx, [pIActiveScriptParse]
  3.                 push edx
  4.         mov edx, [edx]
  5.                 call dword [edx + 0ch]

Загружаем скрипт, используя метод ParseScriptText. У этого метода куча аргументов, но в данном случае мы можем заменить их нулями. Хотя последний, конечно, не желательно, но я, лентяй этакий, поленился найти описание структуры EXCEPINFO и добавить его в заголовочный файл ;)))

Код (Text):
  1.  
  2.         mov edx, [pIActiveScriptParse]
  3.                 mov edx, [edx]
  4.                 mov eax, [pScript]
  5.                 sub ecx, ecx
  6.         push ecx
  7.                 push ecx
  8.         push ecx
  9.                 push ecx
  10.         push ecx
  11.                 push ecx
  12.         push ecx
  13.                 push ecx
  14.         push eax
  15.         push [pIActiveScriptParse]
  16.         call dword [edx + 14h]

После этого движоку будет загружен исходный код скрипта, но выполняться он не будет, до тех пор, пока движок не получит от нас соответствующей команды. Это объясняется тем, что движок сейчас пребывает не в том состоянии. Всего состояний 6, вот они:

Код (Text):
  1.  
  2.             SCRIPTSTATE_UNINITIALIZED
  3.             SCRIPTSTATE_INITIALIZED
  4.             SCRIPTSTATE_STARTED
  5.         SCRIPTSTATE_CONNECTED
  6.             SCRIPTSTATE_DISCONNECTED
  7.             SCRIPTSTATE_CLOSED

Собственно, названия говорят сами за себя, отмечу лишь, что для нас наиболее важно состояние SCRIPTSTATE_CONNECTED - именно оно заставит выполняться загруженный скрипт, поэтому, пользуясь методом SetScriptState, говорим движку, что пора бы уже исполнить чертов скрипт:

Код (Text):
  1.  
  2.         mov edx, [pIActiveScript]
  3.                 mov edx, [edx]
  4.         push SCRIPTSTATE_CONNECTED
  5.         push [pIActiveScript]
  6.             call dword [edx + 14h]
  7.  
  8.         mov edx, [pIActiveScriptSite]
  9.                 mov edx, [edx]
  10.                 push [pIActiveScriptSite]
  11.                 call dword [edx + Addref]
  12.            
  13.             invoke VirtualFree, [pMemory], [buffer_size], MEM_DECOMMIT

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

Код (Text):
  1.  
  2. wmclose:        mov edx, [pIActiveScript]
  3.                 push edx
  4.             mov edx, [edx]
  5.                 call dword [edx + 1Ch]  ;Метод Close
  6.                
  7.                 mov edx, [pIActiveScriptParse]
  8.                 push edx
  9.             mov edx, [edx]
  10.                 call dword [edx + Release]
  11.                
  12.             mov edx, [pIActiveScript]
  13.                 push edx
  14.             mov edx, [edx]
  15.             push [pIActiveScript]
  16.                 call dword [edx + Release]
  17.                
  18.             mov edx, [pIActiveScriptSite]
  19.                 push edx
  20.             mov edx, [edx]
  21.                 call dword [edx + Release]

Надеюсь, коментарии излишни ;)))?

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

Код (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.        
  16.         invoke  DialogBoxParamA, eax, 1000, HWND_DESKTOP, DlgProc, 0
  17.        
  18.         invoke  ExitProcess, 0
  19.  
  20.                
  21. proc DlgProc, hwnd, msg, wparam, lparam
  22.         enter
  23.         cmp [msg], WM_INITDIALOG
  24.         jz wminitdialog
  25.         cmp [msg], WM_COMMAND
  26.         jz wmcommand
  27.         cmp [msg], WM_CLOSE
  28.         jz wmclose
  29.         sub eax, eax
  30.         jmp finish
  31.                
  32. wminitdialog:   mov eax, [hwnd]
  33.         mov [hWnd], eax
  34.                
  35.         invoke VirtualAlloc, 0, MAX_PATH, MEM_COMMIT, PAGE_READWRITE
  36.         mov [szFileName], eax
  37.  
  38.         call Create_Script_Engine
  39.  
  40.         jmp processed
  41.                
  42. wmcommand:  cmp [wparam], BN_CLICKED shl 16 + 1001
  43.         jnz processed
  44.                  
  45.         mov eax, [szFileName]
  46.         mov ecx, 257
  47. @@:     mov byte [eax], 0
  48.         inc eax
  49.         dec ecx
  50.         jnz @B
  51.                
  52.         push szFilter
  53.         push szTitle
  54.         push dword [hwnd]
  55.         call GetFileName
  56.                
  57.         mov ecx, [szFileName]
  58.         mov ecx, [ecx]
  59.         jecxz processed
  60.                
  61.         call Get_Script
  62.         test eax, eax
  63.         jz processed
  64.                
  65.         push eax
  66.         call Run_Script
  67.                
  68.         jmp processed
  69.  
  70. wmclose:    invoke VirtualFree, [szFileName], MAX_PATH, MEM_DECOMMIT
  71.            
  72.         mov edx, [pIActiveScript]
  73.                 push edx
  74.         mov edx, [edx]
  75.                 call dword [edx + Close]
  76.                
  77.                 mov edx, [pIActiveScriptParse]
  78.                 push edx
  79.         mov edx, [edx]
  80.                 call dword [edx + Release]
  81.                
  82.         mov edx, [pIActiveScript]
  83.                 push edx
  84.         mov edx, [edx]
  85.         push [pIActiveScript]
  86.                 call dword [edx + Release]
  87.                
  88.         mov edx, [pIActiveScriptSite]
  89.                 push edx
  90.         mov edx, [edx]
  91.                 call dword [edx + Release]
  92.                
  93.                 invoke  EndDialog, [hwnd], 0
  94.                
  95. processed:  sub eax, eax
  96.         inc eax
  97.        
  98. finish:     return
  99.      
  100. proc Create_Script_Engine
  101.         enter            
  102.            
  103.                 invoke CoInitialize, 0
  104.                
  105.                 invoke CoCreateInstance, CLSID_VBScript, 0, \
  106.                        CLSCTX_INPROC_SERVER, IID_IActiveScript, pIActiveScript
  107.                 test eax, eax
  108.                 js error.create_instance
  109.            
  110.                 invoke LocalAlloc, LMEM_FIXED, 12
  111.                 test eax, eax
  112.                 jz error.alloc
  113.                
  114.                 mov [ActiveScriptSiteObject], eax
  115.            
  116.                 mov dword [eax], pIActiveScriptSite_vtable
  117.                 mov dword [eax + 4], pIActiveScriptSiteWindow_vtable
  118.         mov dword [eax + 8], 1
  119.  
  120.                 mov edx, [pIActiveScript]
  121.                 mov edx, [edx]
  122.                 push pIActiveScriptParse
  123.                 push IID_IActiveScriptParse
  124.                 push [pIActiveScript]
  125.                 call dword [edx + QueryInterface]
  126.                 test eax, eax
  127.                 js .ok
  128.            
  129.                 mov edx, pIActiveScriptSite_vtable
  130.         mov [pIActiveScriptSite], edx
  131.        
  132. .ok:            sub eax, eax
  133.                 return
  134.  
  135. error:
  136.  
  137.  
  138. .alloc:     mov eax, E_OUTOFMEMORY
  139.         return
  140.  
  141. .create_instance:
  142.            
  143.                 sub eax, eax
  144.                 dec eax
  145.                 return
  146.  
  147.  
  148. proc Get_Script
  149.         enter
  150.                
  151.         invoke CreateFileA, [szFileName], GENERIC_READ, FILE_SHARE_READ, \
  152.                             NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL
  153.         test eax, eax
  154.         jz LoadScript.finish
  155.                
  156.         mov [hFile], eax
  157.                
  158.         invoke GetFileSize, eax, 0
  159.        
  160.         mov [FileSize], eax
  161.  
  162.         mov ecx, eax
  163.         inc eax
  164.         inc eax
  165.         shl eax, 1
  166.         push eax
  167.         add eax, ecx
  168.         mov [buffer_size], eax
  169.        
  170.         invoke VirtualAlloc, 0, eax, MEM_COMMIT, PAGE_READWRITE
  171.         mov [pMemory], eax
  172.        
  173.         add eax, dword [FileSize]
  174.         inc eax
  175.         mov [pScript], eax
  176.        
  177.         push eax
  178.         lea ecx, [esp]
  179.         invoke ReadFile, [hFile], [pMemory], [FileSize], ecx, NULL
  180.         pop ecx
  181.                
  182.         invoke CloseHandle, [hFile]
  183.                
  184.         pop eax
  185.  
  186.         invoke MultiByteToWideChar, 0, 0, [pMemory], -1, [pScript], eax
  187.            
  188.             mov eax, [pScript]
  189.  
  190. .finish:    return
  191.                
  192.  
  193.  
  194. proc Run_Script, lpScript
  195.                
  196.         enter
  197.            
  198.         mov edx, [pIActiveScriptSite]
  199.                 mov edx, [edx]
  200.                 push [pIActiveScriptSite]
  201.                 call dword [edx + Addref]
  202.                
  203.                 mov edx, [pIActiveScript]
  204.                 mov edx, [edx]
  205.                 push [pIActiveScriptSite]
  206.                 push [pIActiveScript]
  207.                 call dword [edx + SetScriptSite]
  208.                
  209.                 mov edx, [pIActiveScriptParse]
  210.                 mov edx, [edx]
  211.                 push [pIActiveScriptParse]
  212.                 call dword [edx + InitNew]
  213.                                
  214.                 mov edx, [pIActiveScriptParse]
  215.                 mov edx, [edx]
  216.                 mov eax, [lpScript]
  217.                 sub ecx, ecx
  218.         push ecx
  219.                 push ecx
  220.         push ecx
  221.                 push ecx
  222.         push ecx
  223.                 push ecx
  224.         push ecx
  225.                 push ecx
  226.         push eax
  227.         push [pIActiveScriptParse]
  228.         call dword [edx + ParseScriptText]
  229.                
  230.         mov edx, [pIActiveScript]
  231.                 mov edx, [edx]
  232.         push SCRIPTSTATE_CONNECTED
  233.         push [pIActiveScript]
  234.             call dword [edx + SetScriptState]
  235.            
  236.             mov edx, [pIActiveScriptSite]
  237.                 mov edx, [edx]
  238.                 push [pIActiveScriptSite]
  239.                 call dword [edx + Addref]
  240.            
  241.             invoke VirtualFree, [pMemory], [buffer_size], MEM_DECOMMIT
  242.  
  243.         return
  244.  
  245. proc IActiveScriptSite_GetLCID, pi, plcid        
  246.                 enter
  247.                 mov eax, E_NOTIMPL
  248.                 return
  249.  
  250.  
  251. proc IActiveScriptSite_GetItemInfo, pi, pstrName, dwReturnMask, ppunkItem, ppTypeInfo
  252.                 enter
  253.                 mov eax, TYPE_E_ELEMENTNOTFOUND
  254.         return
  255.  
  256.  
  257. proc IActiveScriptSite_GetDocVersionString, pi, pbstrVersionString
  258.                 enter
  259.                 mov eax, E_NOTIMPL
  260.                 return                
  261.  
  262.  
  263. proc IActiveScriptSite_OnScriptTerminate, pi, pvarResult, pexcepinfo
  264.                enter
  265.                mov eax, S_OK
  266.                return
  267.  
  268.  
  269. proc IActiveScriptSite_OnStateChange, pi, ssScriptState  
  270.                enter
  271.                 mov eax, S_OK
  272.             return
  273.  
  274.  
  275. proc IActiveScriptSite_OnScriptError, pi, pase
  276.             enter
  277.          
  278.                 invoke MessageBoxA, 0, mess1, mess1_title, MB_OK + MB_ICONERROR
  279.         mov eax, S_OK
  280.                return
  281.                
  282.                
  283. proc IActiveScriptSite_OnEnterScript, pi  
  284.                enter
  285.                mov eax, S_OK
  286.                 return
  287.                
  288.                
  289. proc IActiveScriptSite_OnLeaveScript, pi
  290.                enter
  291.                 mov eax, S_OK
  292.             return
  293.                
  294.                
  295. proc IActiveScriptSite_AddRef, pi
  296.                enter      
  297.                mov ecx, [ActiveScriptSiteObject]
  298.                 inc dword [ecx + 8]
  299.                mov eax, [ecx + 8]
  300.                return
  301.                
  302.                
  303. proc IActiveScriptSite_Release, pi
  304.                 enter    
  305.                 mov ecx, [ActiveScriptSiteObject]
  306.                dec dword [ecx + 8]
  307.                 mov eax, [ecx + 8]
  308.                 test eax, eax
  309.                 jnz .ret_
  310.                 invoke LocalFree, ecx
  311. .ret_:          return         
  312.  
  313.  
  314. proc IActiveScriptSite_QueryInterface, pi, iid, ppvObject
  315.                
  316.                 enter
  317.                
  318.                 invoke IsEqualGUID, [iid], IID_IUnknown
  319.                 test eax, eax
  320.                 jnz .s_ok
  321.                
  322.                 invoke IsEqualGUID, [iid], IID_IActiveScriptSite
  323.                 test eax, eax
  324.                 jnz .s_ok
  325.                
  326.                 invoke IsEqualGUID, [iid], IID_IActiveScriptSiteWindow
  327.                 test eax, eax
  328.                 jnz .S_OK_W
  329.                
  330. .NoInterface:   mov eax, E_NOINTERFACE
  331.                
  332.                 return
  333.  
  334. .s_ok:          mov eax, [ActiveScriptSiteObject]
  335.                 mov eax, [eax]
  336.                 mov edx, [ppvObject]
  337.                 mov [edx], eax
  338.                 mov eax, S_OK
  339.                
  340.                 return      
  341.                
  342. .S_OK_W:    mov eax, [ActiveScriptSiteObject]
  343.                 mov eax, [eax + 4]
  344.                mov edx, [ppvObject]
  345.                mov [edx], eax
  346.                mov eax, S_OK                          
  347.         return
  348.  
  349.  
  350. proc IActiveScriptSiteWindow_GetWindow, pi, phwnd
  351.         enter
  352.         mov ecx, [phwnd]
  353.             mov eax, [hWnd]
  354.             mov [ecx], eax
  355.             mov eax, S_OK      
  356.             return
  357.                
  358.  
  359. proc IActiveScriptSiteWindow_EnableModeless, pi, fEnable
  360.             enter
  361.             mov eax, S_OK
  362.             return
  363.                
  364.  
  365. proc GetFileName, hParent, lpTitle, lpFilter
  366.  
  367.         enter
  368.         mov eax, [hParent]
  369.             mov [ofn.hwndOwner], eax
  370.         mov eax, [hInst]
  371.         mov [ofn.hInstance], eax
  372.         mov eax, [lpFilter]
  373.             mov [ofn.lpstrFilter], eax
  374.             mov eax, [szFileName]
  375.             mov [ofn.lpstrFile], eax
  376.             mov [ofn.nMaxFile], MAX_PATH
  377.             mov eax, [lpTitle]
  378.             mov [ofn.lpstrTitle], eax
  379.             mov [ofn.Flags], OFN_EXPLORER or OFN_FILEMUSTEXIST or OFN_LONGNAMES
  380.        
  381.         invoke GetOpenFileName, ofn
  382.        
  383.         return
  384.  
  385.  
  386. section '.data' data readable writeable
  387.  
  388. ofn OPENFILENAMEA
  389.  
  390. mess1 db "Cant't parse it!", 0
  391. mess1_title db 'script engine', 0
  392.  
  393. szFilter db 'VBScripts', 0, '*.vbs', 0, \
  394.         'All files (heh... you can try...)', 0, '*.*',  0, 0
  395.          
  396. szTitle db 'Just open fucking file...', 0
  397. szFileName dd 0
  398.  
  399. hInst dd 0
  400.  
  401. ActiveScriptSiteObject dd 0
  402.  
  403. hWnd dd 0
  404. hFile dd 0
  405. FileSize dd 0
  406. buffer_size dd 0
  407. pMemory dd 0
  408. pScript dd 0
  409.  
  410. pIActiveScript dd 0      
  411. pIActiveScriptParse dd 0      
  412. pIActiveScriptSite dd 0      
  413.    
  414. CLSID_VBScript GUID 0b54f3741h, 5b07h, 11cfh, 0a4h, 0b0h, 0, 0aah, 0, 4ah, 55h, 0e8h                        
  415. IID_IActiveScript GUID 0bb1a2ae1h, 0a4f9h, 11cfh, 8fh, 20h, 0, 80h, 5fh, 2ch, 0d0h, 64h  
  416. IID_IActiveScriptParse GUID 0bb1a2ae2h, 0a4f9h, 11cfh, 8fh, 20h, 0, 80h, 5fh, 2ch, 0d0h, 64h
  417. IID_IActiveScriptSite GUID 0d57d7817h, 0e9b7h, 04a82h, 85h, 74h, 01h, 0d0h, 0f9h, 3dh, 61h, 70h  
  418. IID_IActiveScriptSiteWindow GUID 0d10f6761h, 083e9h, 011cfh, 8fh, 20h, 0, 80h, 5fh, 2ch, 0d0h, 64h
  419. IID_IUnknown GUID 0, 0, 0, 0ch, 0, 0, 0, 0, 0, 0, 46h                        
  420.  
  421. pIActiveScriptSite_vtable dd IActiveScriptSite_vtable
  422. pIActiveScriptSiteWindow_vtable dd IActiveScriptSiteWindow_vtable                          
  423.  
  424.  
  425. IActiveScriptSite_vtable dd IActiveScriptSite_QueryInterface
  426.                          dd IActiveScriptSite_AddRef
  427.                          dd IActiveScriptSite_Release
  428.                          dd IActiveScriptSite_GetLCID
  429.                          dd IActiveScriptSite_GetItemInfo
  430.                          dd IActiveScriptSite_GetDocVersionString
  431.                          dd IActiveScriptSite_OnScriptTerminate
  432.                          dd IActiveScriptSite_OnStateChange
  433.                          dd IActiveScriptSite_OnScriptError
  434.                          dd IActiveScriptSite_OnEnterScript
  435.                          dd IActiveScriptSite_OnLeaveScript
  436.                        
  437. IActiveScriptSiteWindow_vtable  dd IActiveScriptSite_QueryInterface
  438.                             dd IActiveScriptSite_AddRef
  439.                             dd IActiveScriptSite_Release
  440.                 dd IActiveScriptSiteWindow_GetWindow
  441.                 dd IActiveScriptSiteWindow_EnableModeless                        
  442.                            
  443.  
  444. QueryInterface      =   0
  445. Addref              =   4
  446. Release             =   8                
  447. Close           =   1ch
  448. SetScriptSite       =   0ch
  449. InitNew         =   0ch
  450. ParseScriptText     =   14h
  451. SetScriptState      =   14h
  452.  
  453. section '.idata' import data readable writeable
  454. library kernel32, 'kernel32.dll', \
  455.     user32, 'user32.dll', \
  456.         ole32, 'ole32.dll', \
  457.         comdlg32, 'comdlg32.dll'
  458.        
  459. import kernel32, ExitProcess, 'ExitProcess', \
  460.          LocalAlloc, 'LocalAlloc', \
  461.              LocalFree, 'LocalFree', \
  462.              GetModuleHandleA, 'GetModuleHandleA', \
  463.              CreateFileA, 'CreateFileA', \
  464.              CloseHandle, 'CloseHandle', \
  465.              ReadFile, 'ReadFile', \
  466.              GetFileSize, 'GetFileSize', \
  467.              MultiByteToWideChar, 'MultiByteToWideChar', \
  468.              VirtualAlloc, 'VirtualAlloc', \
  469.              VirtualFree, 'VirtualFree'
  470.        
  471. import ole32, CoInitialize, 'CoInitialize', \
  472.               CoCreateInstance, 'CoCreateInstance', \
  473.               CoUninitialize, 'CoUninitialize', \
  474.               IsEqualGUID, 'IsEqualGUID'
  475.  
  476. import user32, DialogBoxParamA, 'DialogBoxParamA', \
  477.            EndDialog, 'EndDialog', \
  478.            MessageBoxA, 'MessageBoxA'
  479.        
  480. import comdlg32, GetOpenFileName, 'GetOpenFileNameA'       
  481.  
  482.  
  483. section '.rsrc' resource data readable
  484.  
  485. directory RT_DIALOG, dialogs
  486.  
  487. resource dialogs, 1000, LANG_ENGLISH+SUBLANG_DEFAULT, main_dlg
  488.  
  489.   dialog main_dlg, 'RunScript', 70, 70, 70, 50, WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
  490.   dialogitem 'BUTTON', 'Execute Script!', 1001, 8, 15, 55, 15, WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON
  491.  
  492. enddialog
  493.  
  494.  
  495. ;---------------------------------------------------------------------
  496. ; RunScript.inc
  497. ;---------------------------------------------------------------------
  498.  
  499. include 'include\win32ax.inc'
  500.  
  501. CLSCTX_INPROC_SERVER            equ 1
  502. CLSCTX_INPROC_HANDLER           equ 2
  503. CLSCTX_LOCAL_SERVER             equ 4
  504. CLSCTX_INPROC_SERVER16          equ 8
  505. CLSCTX_REMOTE_SERVER            equ 10h
  506. CLSCTX_INPROC_HANDLER16     equ 20h
  507. CLSCTX_INPROC_SERVERX86     equ 40h
  508. CLSCTX_INPROC_HANDLERX86        equ 80h
  509. CLSCTX_ESERVER_HANDLER          equ 100h
  510.  
  511. E_NOTIMPL               equ 80004001h
  512. E_NOINTERFACE                       equ 80004002h
  513.  
  514. TYPE_E_ELEMENTNOTFOUND          equ 8002802Bh
  515.  
  516.  
  517. S_OK                                equ 0
  518.  
  519. LMEM_FIXED                          equ 0h
  520.  
  521. E_OUTOFMEMORY                       equ 8007000Eh
  522.  
  523. SCRIPTSTATE_UNINITIALIZED       equ 0h
  524. SCRIPTSTATE_STARTED             equ 1h
  525. SCRIPTSTATE_CONNECTED               equ 2h
  526. SCRIPTSTATE_DISCONNECTED        equ 3h
  527. SCRIPTSTATE_CLOSED              equ 4h
  528. SCRIPTSTATE_INITIALIZED         equ 5h
  529.  
  530.  
  531. struc GUID dd1, dw1, dw2, db1, db2, db3, db4, db5, db6, db7, db8
  532. {
  533. .dd1 dd dd1
  534. .dw1 dw dw1
  535. .dw2 dw dw2
  536. .db1 db db1
  537. .db2 db db2
  538. .db3 db db3
  539. .db4 db db4
  540. .db5 db db5
  541. .db6 db db6
  542. .db7 db db7
  543. .db8 db db8
  544. }
  545.  
  546. MAX_PATH equ 260
  547.  
  548. struc OPENFILENAMEA
  549. {
  550. .lStructSize        dd 4ch
  551. .hwndOwner          dd 0
  552. .hInstance          dd 0
  553. .lpstrFilter        dd 0
  554. .lpstrCustomFilter  dd 0
  555. .nMaxCustFilter     dd 0
  556. .nFilterIndex       dd 0
  557. .lpstrFile          dd 0
  558. .nMaxFile           dd 0
  559. .lpstrFileTitle     dd 0
  560. .nMaxFileTitle      dd 0
  561. .lpstrInitialDir    dd 0
  562. .lpstrTitle         dd 0
  563. .Flags              dd 0
  564. .nFileOffset        dw 0
  565. .nFileExtension     dw 0
  566. .lpstrDefExt        dd 0
  567. .lCustData          dd 0
  568. .lpfnHook           dd 0
  569. .lpTemplateName     dd 0
  570. }
  571. struct OPENFILENAMEA

На сегодня все :smile3:.

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


0 1.338
archive

archive
New Member

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