Статус: Вам и не снилось
Группы: Администраторы
Зарегистрирован: 24.12.2007(UTC) Сообщений: 831 Откуда: Крипто-Про
Сказал(а) «Спасибо»: 1 раз Поблагодарили: 48 раз в 44 постах
|
Для работы с side-by-side ассемблями необходимо использовать API из kernel32.dll: CreateActCtx/ReleaseActCtx – для создания и освобождения контекста активации, ActivateActCtx/DeactivateActCtx – для активирования и деактивирования контекста соответственно. Для работы в .Net удобно использовать следующий класс: Код:public class ActivationContextHelper : IDisposable
{
#region PrivateData
// Activation Context API Functions
[DllImport("Kernel32.dll", SetLastError = true)]
private extern static IntPtr CreateActCtx(ref ACTCTX actctx);
[DllImport("Kernel32.dll", SetLastError = true)]
private extern static bool ActivateActCtx(IntPtr hActCtx, out uint cookie);
[DllImport("Kernel32.dll", SetLastError = true)]
private extern static bool DeactivateActCtx(uint dwFlags, uint cookie);
[DllImport("Kernel32.dll", SetLastError = true)]
private extern static void ReleaseActCtx(IntPtr hActCtx);
[DllImport("Kernel32.dll", SetLastError = true)]
public extern static UInt32 GetCurrentThreadId();
// Activation context structure
private struct ACTCTX
{
public int cbSize;
public uint dwFlags;
public string lpSource;
public ushort wProcessorArchitecture;
public ushort wLangId;
public string lpAssemblyDirectory;
public string lpResourceName;
public string lpApplicationName;
}
// Helpful constants
private const int ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004;
private const int INVALID_HANDLE_VALUE = -1;
// Variables holding information on the activation context
private IntPtr m_hActCtx = (IntPtr)0;
#endregion
// Some helpful error codes // Most likely indicate:
public const UInt32 ERROR_INVALID_PARAMETER = 87; // Missing or empty parameters
public const UInt32 ERROR_ALREADY_INITIALIZED = 1247; // Context already created or active
public const UInt32 ERROR_INVALID_HANDLE = 6; // Context not yet created or not active
/// <summary>
/// Constructor
/// </summary>
public ActivationContextHelper()
{
// This is superfluous - just document zero default
m_hActCtx = (IntPtr)0;
}
/// <summary>
/// Release Windows resources
/// </summary>
void IDisposable.Dispose()
{
Clear();
}
/// <summary>
/// Force the release of Windows resources
/// </summary>
public void Clear()
{
lock (this)
{
if (0 != m_hActCtx.ToInt32())
ReleaseActCtx(m_hActCtx);
m_hActCtx = (IntPtr)0;
}
}
/// <summary>
/// Method to explicitly load a manifest and create an activation context
/// </summary>
/// <param name="manifestPath">Full path to the manifest file</param>
/// <param name="rootFolder">'null' or the root assembly probing directory</param>
/// <returns>'true' - success, 'false' - failure</returns>
public bool CreateContext(string manifestPath, string rootFolder, out UInt32 dwError)
{
// Verify parameters, exit if not acceptable
if (null == manifestPath || "" == manifestPath)
{
dwError = ERROR_INVALID_PARAMETER;
return false;
}
// Build the activation context information structure
ACTCTX info = new ACTCTX();
info.cbSize = Marshal.SizeOf(typeof(ACTCTX));
info.dwFlags = 0;
info.lpSource = manifestPath;
if (null != rootFolder && "" != rootFolder)
{
info.lpAssemblyDirectory = rootFolder;
info.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
}
bool bOK = true;
dwError = 0;
// Protect from changes by multiple threads
lock (this)
{
// It is illegal to create a context while one is already created
if (0 != m_hActCtx.ToInt32())
{
dwError = ERROR_ALREADY_INITIALIZED;
bOK = false;
}
else
{
// Create the activation context
m_hActCtx = CreateActCtx(ref info);
if (-1 == m_hActCtx.ToInt32())
{
dwError = (UInt32)Marshal.GetLastWin32Error();
m_hActCtx = (IntPtr)0;
bOK = false;
}
}
}
return bOK;
}
/// <summary>
/// Activate the previously created activation context
/// </summary>
/// <returns>'true' - success, 'false' - failure</returns>
public UInt32 ActivateContext(out UInt32 dwError)
{
UInt32 cookie = 0;
dwError = 0;
lock (this)
{
// We cannot activate a context if we do not have it.
if (0 == m_hActCtx.ToInt32())
{
dwError = ERROR_INVALID_HANDLE;
}
else
{
// Activate the context
if (!ActivateActCtx(m_hActCtx, out cookie))
{
cookie = 0;
dwError = (UInt32)Marshal.GetLastWin32Error();
}
}
}
return cookie;
}
/// <summary>
/// Create the activation context, if one is not created yet then
/// immediately activate it.
/// </summary>
/// <param name="manifestPath"></param>
/// <param name="rootFolder"></param>
/// <param name="dwError"></param>
/// <returns></returns>
public UInt32 CreateAndActivate(string manifestPath, string rootFolder, out UInt32 dwError)
{
UInt32 cookie = 0;
lock (this)
{
// If we already have a context or we successfully create one - activate.
if (0 != m_hActCtx.ToInt32() || CreateContext(manifestPath, rootFolder, out dwError))
{
cookie = ActivateContext(out dwError);
}
}
return cookie;
}
/// <summary>
/// Deactivate the previously activated activation context
/// </summary>
/// <returns>'true' - success, 'false' - failure</returns>
public bool DeactivateContext(UInt32 cookie, out UInt32 dwError)
{
bool bOK = true;
dwError = 0;
lock (this)
{
// We cannot deactivate a context if we do not have it or it is not activated
if (0 == m_hActCtx.ToInt32() || 0 == cookie)
{
dwError = ERROR_INVALID_HANDLE;
bOK = false;
}
else
{
// Deactivate the context, may throw an exception if bad sequence
if (!DeactivateActCtx(0, cookie))
{
dwError = (UInt32)Marshal.GetLastWin32Error();
bOK = false;
}
}
}
return bOK;
}
/// <summary>
/// Release the previously created activation context. Note that the
/// context is silently released by 'Clear' and 'Dispose'.
/// </summary>
/// <returns>'true' - success, 'false' - failure</returns>
public bool ReleaseContext(out UInt32 dwError)
{
bool bOK = true;
dwError = 0;
lock (this)
{
if (0 == m_hActCtx.ToInt32())
{
dwError = ERROR_INVALID_HANDLE;
bOK = false;
}
else
{
ReleaseActCtx(m_hActCtx);
m_hActCtx = (IntPtr)0;
bOK = true;
}
}
return bOK;
}
}
Использование:
• Создать в каталоге с исходными кодами вашего приложения файл YourApp.manifest, содержащий манифест, описанный выше. Пример для cades.dll:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="CompanyName.ProductName.YourApplication"
type="win32"
/>
<description></description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="CryptoPro.PKI.CAdES"
version="1.0.0.0"
processorArchitecture="x86"
publicKeyToken="a6d31b994cfcddc4"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
• В коде, где необходимо использовать функции из ассембли, необходимо:
o Описать все используемые функции и структуры данных, используя .Net Interop
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CADES_SIGN_MESSAGE_PARA
{
/// <summary>
/// uint dwSize
/// </summary>
public uint dwSize;
/// <summary>
/// PCRYPT_SIGN_MESSAGE_PARA pSignMessagePara
/// </summary>
//public CryptoAPI.CRYPT_SIGN_MESSAGE_PARA pSignMessagePara;
public IntPtr pSignMessagePara;
/// <summary>
/// CADES_SIGN_PARA pCadesSignPara
/// </summary>
public IntPtr pCadesSignPara;
}
[DllImport(“cades.dll”, EntryPoint = "CadesSignMessage", SetLastError = true,
CallingConvention = CallingConvention.StdCall)]
private static extern bool CadesSignMessageImpl(
ref CADES_SIGN_MESSAGE_PARA pSignPara,
bool fDetachedSignature,
uint cToBeSigned,
String[] rgpbToBeSigned,
uint[] rgcbToBeSigned,
ref IntPtr ppSignedBlob);
o Создать и активировать контекст
UInt32 dwError = 0;
ActivationContextHelper actCtxHelper = new ActivationContextHelper();
UInt32 savedCookie = actCtxHelper.CreateAndActivate(“YourAppPath\YourApp.manifest”, “YourAppPath”, out dwError);
o Вызвать нужные функции
o Деактивировать и освободить контекст
If(!actCtxHelper.DeactivateContext(savedCookie, out dwError)) {
// …
}
If (!actCtxHelper.ReleaseContext(out dwError)) {
// …
}
Дополнение: примеры по использованию данного класса в Asp .Net можно посмотреть здесь и скачать здесь от “Maze Computer Communications, Inc.” Отредактировано пользователем 18 января 2008 г. 16:57:12(UTC)
| Причина: Не указана |
|