Marshaling data from an unmanaged buffer variable.



I'm trying to use
http://msdn.microsoft.com/en-us/library/aa382711(VS.85).aspx function in
..NET.

p/invoke data type conversion:
http://msdn.microsoft.com/en-us/library/ac7ay120.aspx

BOOL WINAPI EcGetSubscriptionRunTimeStatus(
__in LPCWSTR SubscriptionName,
__in EC_SUBSCRIPTION_RUNTIME_STATUS_INFO_ID StatusInfoId,
__in LPCWSTR EventSourceName,
__in DWORD Flags,
__in DWORD StatusValueBufferSize,
__in PEC_VARIANT StatusValueBuffer,
__out PDWORD StatusValueBufferUsed
);


This is my prototype in VB.NET

Private Declare Unicode Function EcGetSubscriptionRunTimeStatus Lib
"wecapi.dll" _
(ByVal SubscriptionName As String, _
ByVal StatusInfoId As EC_SUBSCRIPTION_RUNTIME_STATUS_INFO_ID, _
ByVal EventSourceName As String, _
ByVal Flags As UInt32, _
ByVal StatusValueBufferSize As UInt32, _
ByVal StatusValueBuffer As IntPtr, _
ByRef StatusValueBufferUsed As UInt32) _
As Boolean

I do not know how to get the data from the StatusValueBuffer. What value do
I pass to it? Is it even the right data-type? Can someone shed some light
on this interop problem? Would tlbimp.exe be helpful in this case?

Here is a usage example in C++:
http://msdn.microsoft.com/en-us/library/bb513655(VS.85).aspx

Thanks!

UPDATE...

I got it to work somewhat... (I wish I understood what is going on here!)

The second call to EcGetSubRTS returns code other than 0... so I assume that
it fails. However, changing the StatusValuebuffer to Byte() returns
(1000000020000000). And I have confirmed that position 0 is the actual
status. Here is the code used:

1 Imports System.Runtime.InteropServices
2 Imports System.Reflection
3
4 Public Class Form2
5
6 Private Const ERROR_SUCCESS As UInt16 = 0
7
8
9 Private Enum EC_SUBSCRIPTION_RUNTIME_STATUS_INFO_ID As UInt32
10 EcSubscriptionRunTimeStatusActive = 0
11 EcSubscriptionRunTimeStatusLastError = 1
12 EcSubscriptionRunTimeStatusLastErrorMessage = 2
13 EcSubscriptionRunTimeStatusLastErrorTime = 3
14 EcSubscriptionRunTimeStatusNextRetryTime = 4
15 EcSubscriptionRunTimeStatusEventSources = 5
16 EcSubscriptionRunTimeStatusLastHeartbeatTime = 6
17 End Enum
18
19 Private Enum EC_SUBSCRIPTION_RUNTIME_STATUS_ACTIVE_STATUS As UInt32
20 EcRuntimeStatusActiveStatusDisabled = 1
21 EcRuntimeStatusActiveStatusActive = 2
22 EcRuntimeStatusActiveStatusInactive = 3
23 EcRuntimeStatusActiveStatusTrying = 4
24 End Enum
25
26 Private Declare Unicode Function EcOpenSubscription Lib "wecapi.dll"
(ByVal SubscriptionName As String, ByVal AccessMask As UInt32, ByVal Flags As
UInt32) As IntPtr
27
28 Private Declare Unicode Function EcGetSubscriptionRunTimeStatus Lib
"wecapi.dll" (ByVal SubscriptionName As String, ByVal StatusInfoId As
EC_SUBSCRIPTION_RUNTIME_STATUS_INFO_ID, ByVal EventSourceName As String,
ByVal Flags As UInt32, ByVal StatusValueBufferSize As UInt32, ByVal
StatusValueBuffer As Byte(), ByRef StatusValueBufferUsed As UInt32) As
Boolean
29
30 Private Declare Unicode Function EcClose Lib "wecapi.dll" (ByVal
SubHandle As IntPtr) As Boolean
31
32 Private Sub GetSubStatus(ByVal SubscriptionName As String)
33 Dim ec_handle As IntPtr
34 Dim dwRetVal As UInt32
35 Dim vStatusBuffer As Byte() = Nothing
36 Dim vStatusSize As UInt32
37 Dim vStatusUsed As UInt32
38 Dim er As Int16
39
40 Try
41 ec_handle = EcOpenSubscription(SubscriptionName, 1, 2)
42
43 If ec_handle <> IntPtr.Zero Then
44 dwRetVal =
EcGetSubscriptionRunTimeStatus(SubscriptionName, _
45
EC_SUBSCRIPTION_RUNTIME_STATUS_INFO_ID.EcSubscriptionRunTimeStatusActive, _
46 vbNullString, _
47 Nothing, _
48 vStatusSize, _
49 vStatusBuffer, _
50 vStatusUsed)
51 If dwRetVal = ERROR_SUCCESS And vStatusUsed > 0 Then
52
53 Array.Resize(vStatusBuffer, vStatusUsed)
54
55 dwRetVal =
EcGetSubscriptionRunTimeStatus(SubscriptionName, _
56
EC_SUBSCRIPTION_RUNTIME_STATUS_INFO_ID.EcSubscriptionRunTimeStatusActive, _
57 vbNullString, _
58 Nothing, _
59 vStatusBuffer.Length, _
60 vStatusBuffer, _
61 vStatusUsed)
62
63 If dwRetVal = ERROR_SUCCESS Then
64 MsgBox(vStatusBuffer.GetValue(0).tostring)
65 Else
66 MsgBox("err : runtimestatus2 : " &
dwRetVal.ToString)
67 End If
68
69 ''--------------------------------------------------
70 'Dim tempBuffer As IntPtr =
Marshal.AllocHGlobal(CInt(vStatusUsed))
71 'Dim tempBufferInt As UInt32 = tempBuffer.ToInt32
72
73 'dwRetVal =
EcGetSubscriptionRunTimeStatus(SubscriptionName, _
74 '
EC_SUBSCRIPTION_RUNTIME_STATUS_INFO_ID.EcSubscriptionRunTimeStatusActive, _
75 'vbNullString, _
76 'Nothing, _
77 'tempBufferInt, _
78 'vStatusBuffer, _
79 'vStatusUsed)
80
81 'Dim buffer(tempBufferInt) As Byte
82 'Marshal.Copy(tempBufferInt, buffer, 0, vStatusUsed)
83 ''------------------------------------------------
84
85
86
87 'MsgBox(Marshal.ReadInt16(vStatusBuffer))
88 ' MsgBox(Marshal.PtrToStringAuto(vStatusBuffer, 16))
89 MsgBox(dwRetVal.ToString & " : buffSize" &
vStatusSize.ToString & _
90 " : buffUsed" & vStatusUsed.ToString & _
91 " : Buff" & vStatusBuffer.ToString)
92 Else
93 MsgBox("err : runtimestatus : " & dwRetVal.ToString)
94 End If
95
96
97 Else
98 er = Marshal.GetLastWin32Error
99 MsgBox("win32 er: ec_handle = 0 : " & er.ToString)
100 End If
101
102
103 Catch ex As Exception
104 MsgBox(ex.Message)
105 Finally
106 If ec_handle <> IntPtr.Zero Then
107 EcClose(ec_handle)
108 End If
109 End Try
110 End Sub
111
112 Private Sub btnGetStat_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnGetStat.Click
113 Try
114 GetSubStatus(txtSubName.Text.Trim)
115
116 Catch ex As Exception
117 MsgBox(ex.Message)
118 End Try
119 End Sub
120
121 Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
122
123 End Sub
124 End Class

.


Loading