[DllImport("SignLib.dll")]
private static extern bool DoSign(
Int32 dSI,
Int32 dPI,
byte[] message,
Int32 dMesSize,
[MarshalAs(UnmanagedType.LPArray)]ref byte[] chSignedMes,
ref Int32 dSignedSize);
Помогите с C++ dll
помогите с траблой!
Есть такое описание функции в библиотеке
BOOL DoSign(DWORD dSI,DWORD dPI,BYTE* message,DWORD dMesSize,BYTE** chSignedMes,DWORD* dSignedSize);
подпись сообщения.
message - исходное сообщение для отсылки
dMesSize - размер исходного сообщения без завершающего нулевого байта
chSignedMes - указатель на буфер в который будет записано готовое, подписанное сообщение. Если NULL, то в dSignedSize вернется размер необходимого буфера.
dSignedSize -
на входе - указатель на размер буфера, на который указывает chSignedMes,
на выходе -
при возвращении функцией FALSE или 0:
0 - при ошибке и
размер необходимого буфера при chSignedMes=NULL или малом значении dSignedSize
при возвращении функцией TRUE или 1 - размер подписанного и сконвертированного сообщения, записанного в буфер chSignedMes
я ее описываю в C# следующим образом:
Код:
вызываю так:
Код:
DoSign(
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
Encoding.Unicode.GetBytes(message),
Encoding.Unicode.GetBytes(message).Length,
ref chSignedMes,
ref dSignedSize);
chSignedMes = new byte[dSignedSize];
DoSign(
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
Encoding.ASCII.GetBytes(message),
Encoding.ASCII.GetBytes(message).Length,
ref chSignedMes,
ref dSignedSize)
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
Encoding.Unicode.GetBytes(message),
Encoding.Unicode.GetBytes(message).Length,
ref chSignedMes,
ref dSignedSize);
chSignedMes = new byte[dSignedSize];
DoSign(
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
Encoding.ASCII.GetBytes(message),
Encoding.ASCII.GetBytes(message).Length,
ref chSignedMes,
ref dSignedSize)
и после всего этого в chSignedMes всего один символ, хотя dSignedSize=259
Вроде уже перепробовал все, что мог... :(
Буду благодарен за любую помощь!
...BYTE** chSignedMes...
chSignedMes - указатель на буфер
т.е. должно быть:
BYTE *chSignedMes?
указатель на указатель и указатель на буфер - ИМХО не совсем одно и тоже.
Возможно в этом и ошибка? Посмотрите как функция на самом деле экспортируеться.
к сожалению, не могу посмотреть исходники тк есть только dll.
на данный момент справился с импортом с помощью неуправляемого кода (unsafe), но вот новая проблема, при выходе из функции, где все это дело делается, вылетает exception:
The runtime has encountered a fatal error. The address of the error was at 0x7a2b5aec, on thread 0x1478. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
может знаете в чем проблема, ибо я теряюсь(
код теперь выглядит так:
Код:
public static string GetSignedMsg(string message, ConfigInfo cfg)
{
string res = "";
unsafe
{
try
{
if (!InitLib(
cfg.KeyFilePath,
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
false,
cfg.PrivateKeyPsw))
{
return null;
}
int dSignedSize = 0;
byte chSignedMes;
byte* PchSignedMes = &chSignedMes;
DoSign(
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
//Encoding.Unicode.GetBytes(message),
//Encoding.Unicode.GetBytes(message).Length,
message,
message.Length,
&PchSignedMes,
ref dSignedSize);
int j = dSignedSize;
//chSignedMes = new byte[dSignedSize];
//chSignedMes=new StringBuilder();
if (!DoSign(
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
//Encoding.Unicode.GetBytes(message),
//Encoding.Unicode.GetBytes(message).Length,
message,
message.Length,
&PchSignedMes,
ref dSignedSize))
{
return null;
}
byte[] data = new byte[j];
for (int i = 0; i < j; i++)
{
data = *PchSignedMes;
PchSignedMes++;
}
//string str = Encoding.ASCII.GetString(data);
//res = str;
Deinit();
return Encoding.ASCII.GetString(data);
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
}
return res;
}
{
string res = "";
unsafe
{
try
{
if (!InitLib(
cfg.KeyFilePath,
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
false,
cfg.PrivateKeyPsw))
{
return null;
}
int dSignedSize = 0;
byte chSignedMes;
byte* PchSignedMes = &chSignedMes;
DoSign(
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
//Encoding.Unicode.GetBytes(message),
//Encoding.Unicode.GetBytes(message).Length,
message,
message.Length,
&PchSignedMes,
ref dSignedSize);
int j = dSignedSize;
//chSignedMes = new byte[dSignedSize];
//chSignedMes=new StringBuilder();
if (!DoSign(
Int32.Parse(cfg.ClientID),
Int32.Parse(cfg.PosID),
//Encoding.Unicode.GetBytes(message),
//Encoding.Unicode.GetBytes(message).Length,
message,
message.Length,
&PchSignedMes,
ref dSignedSize))
{
return null;
}
byte[] data = new byte[j];
for (int i = 0; i < j; i++)
{
data = *PchSignedMes;
PchSignedMes++;
}
//string str = Encoding.ASCII.GetString(data);
//res = str;
Deinit();
return Encoding.ASCII.GetString(data);
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
}
return res;
}
Во вторых - посмотрите - что все же экспортирует ваша длл. Для этого исходники не нужны.
После рабочего дня голова уже не варит - потому ничего не могу сказать по поводу его корректности - если в инете есть описание библиотеки - кинте - с утра гляну.
2) если б знал как, то посмотрел... )
3) вряд ли описание библиотеки есть в интернете, тк она была написана фирмой-клиентом для своих криптографических нужд. по крайней мере гугл о ней ничего не знает...
Код:
byte chSignedMes;
byte* PchSignedMes = &chSignedMes;
byte* PchSignedMes = &chSignedMes;
в данном месте был объявлен байт и указатель на него, а надо указатель на массив размера chSignedMes.
Поэтому при первом вызове функции DoSign(...) вместо PchSignedMes надо передавать 0, а перед вторым вызовом нужно написать:
Код:
byte* PchSignedMes = stackalloc byte[dSignedSize];
и передавать &PchSignedMes.