Рассмотрим следующий фрагмент кода .NET:
byte[] hash = { 0x60, 0x2B, 0x45, 0x9D, 0xA0, 0x6D, 0xD5, 0x02, 0x43, 0x86, 0xC1, 0xBA, 0x6B, 0x14, 0x37, 0x88, 0x63, 0x08, 0x39, 0xA0 };
using (var adminBase = TemporaryComObject.Wrap(new MSAdminBase_W()))
using (var ptrHash = new AllocHGlobal(hash))
{
using (var siteKey = new AdminBaseKey(adminBase.Com, adminBase.Com.OpenKey(METADATA_MASTER_ROOT_HANDLE, "/LM/W3SVC/1", METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10000)))
{
var record = new METADATA_RECORD
{
dwMDIdentifier = 5506,
dwMDAttributes = METADATA_INHERIT,
dwMDUserType = IIS_MD_UT_SERVER,
dwMDDataType = BINARY_METADATA,
pbMDData = ptrHash.Buffer,
dwMDDataLen = hash.Length
};
adminBase.Com.SetData(siteKey.Handle, string.Empty, ref record);
}
adminBase.Com.SaveData();
}
Этот код пытается установить свойство метабазы SSLCertHash IIS6 из .NET.
Он работает абсолютно нормально, если приложение .NETскомпилирован для x86, что означает, что в соответствующем файле .csproj найдена следующая строка:
<PlatformTarget>x86</PlatformTarget>
Однако драконы приходят, когда я пропускаю эту строку и компилирую для AnyCPU.А именно, происходит то, что inetinfo.exe падает с нарушением прав доступа.Вот соответствующий снимок окна вывода windbg:
(24f0.cbc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
msvcrt!memmove+0x1e5:
000007fe`fe371111 8b040a mov eax,dword ptr [rdx+rcx] ds:00000000`00000010=????????
0:001> k
Child-SP RetAddr Call Site
00000000`008ee1f8 000007fe`f5a64e71 msvcrt!memmove+0x1e5
00000000`008ee200 000007fe`f5a64da0 abocomp!PROPERTY_ENTRY::Create+0x79
00000000`008ee230 000007fe`f5a5c21b abocomp!PROPERTY_BAG::SetData+0xbc
00000000`008ee270 000007fe`f5a6088a abocomp!ABO_NODE::SetData+0xa3
00000000`008ee2a0 000007fe`f5a9456f abocomp!ABO_WRAPPER::SetData+0x1ca
00000000`008ee580 000007fe`f5ad3e54 COADMIN!CADMCOMW::SetData+0x127
00000000`008ee630 000007fe`fdfd51d0 ADMWPROX!IMSAdminBaseW_R_SetData_Thunk+0xb4
00000000`008ee6b0 000007fe`fdedf16e RPCRT4!NdrStubCall2+0xa36
00000000`008eecd0 000007fe`fdee0ccd ole32!CStdStubBuffer_Invoke+0x8b
00000000`008eed00 000007fe`fdee0c43 ole32!SyncStubInvoke+0x5d
00000000`008eed70 000007fe`fdd9a4f0 ole32!StubInvoke+0xdb
00000000`008eee20 000007fe`fdee14d6 ole32!CCtxComChnl::ContextInvoke+0x190
00000000`008eefb0 000007fe`fdee122b ole32!AppInvoke+0xc2
00000000`008ef020 000007fe`fdedfd6d ole32!ComInvokeWithLockAndIPID+0x52b
00000000`008ef1b0 000007fe`fdfa50f4 ole32!ThreadInvoke+0x30d
00000000`008ef250 000007fe`fdfa4f56 RPCRT4!DispatchToStubInCNoAvrf+0x14
00000000`008ef280 000007fe`fdfa775b RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x146
00000000`008ef3a0 000007fe`fdfa769b RPCRT4!RPC_INTERFACE::DispatchToStub+0x9b
00000000`008ef3e0 000007fe`fdfa7632 RPCRT4!RPC_INTERFACE::DispatchToStubWithObject+0x5b
00000000`008ef460 000007fe`fdfa532d RPCRT4!LRPC_SCALL::DispatchRequest+0x422
00000000`008ef540 000007fe`fdfc2e7f RPCRT4!LRPC_SCALL::HandleRequest+0x20d
00000000`008ef670 000007fe`fdfc2a35 RPCRT4!LRPC_ADDRESS::ProcessIO+0x3bf
00000000`008ef7b0 00000000`7753b68b RPCRT4!LrpcIoComplete+0xa5
00000000`008ef840 00000000`7753feff ntdll!TppAlpcpExecuteCallback+0x26b
00000000`008ef8d0 00000000`76e5652d ntdll!TppWorkerThread+0x3f8
00000000`008efbd0 00000000`7754c521 kernel32!BaseThreadInitThunk+0xd
00000000`008efc00 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
0:001> g
(24f0.cbc): Access violation - code c0000005 (!!! second chance !!!)
msvcrt!memmove+0x1e5:
000007fe`fe371111 8b040a mov eax,dword ptr [rdx+rcx] ds:00000000`00000010=????????
Я абсолютно не знаю, что происходит.А вы?
Дополнительная информация
- Я использую 64-разрядную версию Windows 7, IIS 7.5 с включенной метабазой IIS6
- Я не использую
System.DirectoryServices
для изменения свойства метабазы SSLCertHash, потому что это невозможно - http://support.microsoft.com/kb/313624 объясняет это. Эта статья содержит более полезную информацию по теме. - Типы
TemporaryComObject
, AllocHGlobal
, AdminBaseKey
гарантируют, что COM-объект, неуправляемая память и базовый ключ администратора освобождены от свойства./closed. - Сборка взаимодействия для COM-объекта MSAdminBase была получена с использованием варианта описанной здесь методики - http://www.moserware.com/2009/04/using-obscure-windows-com-apis-in-net.html. Только я не воссоздал код взаимодействия, а скорее соответствующий файл IDL.Затем я скомпилировал его с помощью MIDL для создания соответствующего файла TLB, который я передал в TlbImp для создания сборки взаимодействия.
Определение C типа METADATA_RECORD найдено в файле mddefw.h из SDK.:
typedef struct _METADATA_RECORD
{
DWORD dwMDIdentifier;
DWORD dwMDAttributes;
DWORD dwMDUserType;
DWORD dwMDDataType;
DWORD dwMDDataLen;
unsigned char *pbMDData;
DWORD dwMDDataTag;
} METADATA_RECORD;
В созданной мной сборке взаимодействия тип объявляется так:
[StructLayout(LayoutKind.Sequential, Pack=4), ComConversionLoss]
public struct METADATA_RECORD
{
public int dwMDIdentifier;
public int dwMDAttributes;
public int dwMDUserType;
public int dwMDDataType;
public int dwMDDataLen;
[ComConversionLoss]
public IntPtr pbMDData;
public int dwMDDataTag;
}
Обратите внимание на наличие атрибута ComConversionLoss
.Я не знаю, имеет ли это значение или нет, но когда я создал сборку взаимодействия, я получил следующее предупреждение:
TlbImp : warning TI3016: The type library importer could not convert the signature for the member 'MSAdminBaseLib.METADATA_RECORD.pbMDData'. [C:\Work\IISCertObj\SimpleNCServerSecurity.csproj]
Есть еще один мой пост (пока без ответа), который касаетсяименно с этой проблемой.
Большое спасибо.
РЕДАКТИРОВАТЬ
У меня такое ощущение, что оно имеет отношение к StructLayout.Pack = 4
.Я еще учусь, как заставить TlbImp не вставлять его ...
EDIT2
И действительно, это проблема.Как выясняется, вывод, производимый TlbImp, требует дальнейшей настройки.Мне пришлось разобрать его с помощью Reflector.NET и удалить явные инструкции Pack.Теперь все отлично работает.