Проблема. Хочу написать (почти написал) native dll на VBasic'е 6.0. Эта dll подключается как бы в качестве плагина для Mathsoft Mathcad 11. Мне не нужна таблица экспорта. Библиотека расширяет набор функций математической системы, но делает это вызовом функции регистрации из другой dll при первичной загрузки программы.
Сейчас регистрация срабатывает и Mathcad добавляет функцию себе в набор пользовательских функций, но беда в том, что сразу после регистрации моя библиотека выгружается по ошибке. Я протрейсил все call'ы и дошёл до того места, где проблема, она оказалась в строке:
- Код: Выделить всё
08C349D3 FF15 2C10C308 CALL DWORD PTR DS:[<&MSVBVM60.__vbaSetSystemError>]
Вот кода модуля:
- Код: Выделить всё
Option Explicit
Private Const DLL_PROCESS_ATTACH As Long = 1
Private Const DLL_PROCESS_DETACH As Long = 0
Private Const DLL_THREAD_ATTACH As Long = 2
Private Const DLL_THREAD_DETACH As Long = 3
' Глобальные константы
'// types to be used in declaration of the function's
'// arguments and of the return value
'#define COMPLEX_SCALAR 1
Public Const COMPLEX_SCALAR = 1
'#define COMPLEX_ARRAY 2
Public Const COMPLEX_ARRAY = 2
'#define STRING 8
Public Const CSTRING = 8 ' STRING - builtin type
'// your function will be passed a const char * pointer
'#define INFILE 13
Public Const INFILE = 13
'// an OUTFILE is like an INFILE except it allows you
'// to put your function on the left side of a := like
'// the WRITEPRN() builtin
'#define OUTFILE 14
Public Const OUTFILE = 14
'// use this structure to create a function
'#define MAX_ARGS 10
Public Const MAX_ARGS = 10
' Тип - описатель функции
Type FUNCTIONINFO
lpstrName As String
lpstrParameters As String
lpstrDescription As String
lpfnMyCFunction As Long
returnType As Long
nArgs As Long
argType(MAX_ARGS - 1) As Long
End Type
'const void * CreateUserFunction( HINSTANCE, FUNCTIONINFO * );
Declare Function CreateUserFunction Lib "mcaduser.dll" (ByVal hInst As Long, FuncInfo As FUNCTIONINFO) As Long
' Описание тестовой функции пользователя
Global mcadVBTest01Info As FUNCTIONINFO
Function mcadVBTest01(lpOut As Long, lpIn As Long) As Long
' Комментарий
mcadVBTest01 = 0
End Function
Private Function ReturnMe(ByVal a As Long) As Long
ReturnMe = a
End Function
Public Function DllMain(ByVal hInstDll As Long, ByVal fdwReason As Long, ByVal lpvReserved As Long) As Long
Dim Res As Long
'TODO:
'Поместите здесь код инициализации библиотеки.
Select Case fdwReason
Case DLL_PROCESS_ATTACH
With mcadVBTest01Info
.lpstrName = "Test01"
.lpstrParameters = "Parameters"
.lpstrDescription = "Description"
.lpfnMyCFunction = ReturnMe(AddressOf mcadVBTest01)
.returnType = COMPLEX_SCALAR
.nArgs = 1
.argType(0) = COMPLEX_SCALAR
End With
Res = CreateUserFunction(hInstDll, mcadVBTest01Info)
Err.Clear
DllMain = 1 ' return TRUE
Case DLL_PROCESS_DETACH
'
Case DLL_THREAD_ATTACH
'
Case DLL_THREAD_DETACH
'
End Select
End Function
Public Sub Exporting()
'TODO:
'Поместите тут Exports для каждой функции, которую нужно экспортировать.
Exports "About", AddressOf MyProc
Base &H400000 'Базу можно указать вручную, а можно не указывать.
End Sub
Public Sub MyProc()
'тут процедуры
End Sub
'TODO:
'Поместите тут экспортируемые функции.
'Не хотите тут - пожалуйста, помещайте где угодно. Но регистрацию Exports - здесь.
- Код: Выделить всё
CreateUserFunction(hInstDll, mcadVBTest01Info)
Вот фрагмент работы этого кода под Olly (на снимке выполнена команда CreateUserFunction() - .text:08C349CE, а далее код уходит в астрал ntdll):
Вопрос к профи. Откудова растут ноги у ошибки? Мне нужно, чтобы dll не выгружалась хотя бы. Регистрация происходит успешно и Mathcad переходит в функцию, указанную в структуре, только вот, когда dll выгружена, то переходит он невесть куда, от чего возникает ошибка.
Что за функция SetSysytemError() ?
P.S. Я немного ошибся, функция регистрации ещё не выполнена. Она как раз собирается выполниться. Точка останова на ней более темная.