Autor Beitrag
CopWorker1
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 20.10.20 11:33 
Hallo zusammen,

Ich versuche eine Kommunikation zwischen einem in C++ geschriebenen Prozess und einem in C# geschriebenen Prozess herzustellen.
Jeder Prozess hat einen RPC-Server und einen RPC-Client.

Die folgende Situation besteht:
Es ist möglich, eine korrekte RPC-Kommunikation zwischen zwei in C++ geschriebenen Prozessen zu starten.
Außerdem ist es möglich, eine korrekte RPC-Kommunikation zwischen zwei in C# geschriebenen Prozessen zu starten.

Es ist nicht möglich, eine korrekte RPC-Kommunikation zwischen einem in C++ geschriebenen Prozess und einem in C# geschriebenen Prozess zu starten.

Der Fehler tritt in der Funktion "NdrGetBuffer (,,)" auf.
Der Client verwendet diese Funktion, um einen Zeiger vom RPC-Server abzurufen und die erforderlichen Daten zu senden.

Ich weiß nicht, wie ich es jetzt machen soll.
Gibt es irgendetwas, das in den Benutzereinstellungen eingerichtet werden muss?

Kann mir jemand helfen?
Vielen Dank.
Fujitsufan


Moderiert von user profile iconTh69: Topic aus C# - Die Sprache verschoben am Di 20.10.2020 um 13:19
Moderiert von user profile iconTh69: Falsche Schreibweisen von C++ und C# korrigiert (c ++, c #).
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 20.10.20 12:51 
RPC ist ein allgemeiner Begriff, da steht aber eigentlich kein genau bestimmtes Verfahren dahinter.
Welches Verfahren benutzt du also? Wenn du kannst zeig auch ein wenig Code.
CopWorker1 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 20.10.20 15:02 
Hallo Ralf Jansen,

vielen Dank für deine Hilfe, erstmals.

Dann kann ich dir noch die Initialisierungsroutinen von Server und Client zukommen lassen.
Diese zwar in gekürzter Form. Alles darf ich dir nicht zeigen.

Protokoll: ncacn_ip_tcp;
Endpoint: Client = 2000, Server = 2000;
NetworkAdress: Mein Rechername;

Ich greife dabei beim Server und beim Client jeweils auf 3 Funktionen zu, alle definiert in "rpcdce.h".

Beim Server:
RpcServerRegisterIf(,,); RpcServerUseProtseqEpW(,,); RpcServerRegisterAuthInfoW(,,,);

Beim Client:
RpcStringBindingComposeW(,,,,); RpcBindingFromStringBindingW(,); RpcBindingSetAuthInfoW(,,,,);

Siehe anhängende Dateien (RpcInitClientReduziert.txt, RpcInitServerReduziert.txt)

Grüße von CopWorker1
Einloggen, um Attachments anzusehen!
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 20.10.20 15:24 
Hallo und :welcome:

so wirst du aber kaum hilfreiche Antworten bekommen (der C++ Code alleine nützt hierbei nicht viel).
Du solltest uns deinen C#-Code zeigen (ich nehme mal an, der beruht dann auf P/Invoke-Aufrufen der "rpcrt4.dll"?) und genau schreiben, welchen Fehler du erhältst.


Zuletzt bearbeitet von Th69 am Di 20.10.20 15:45, insgesamt 1-mal bearbeitet
CopWorker1 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 20.10.20 15:42 
Hallo Th69,

jetzt bist du mir gerade 10 min. zuvorgekommen.
Diese habe ich soeben erstellt.

Da sind die einzelnen Passagen drin.
Die stammen aus der "rpcrt4.dll".

Siehe Anhang.

Vielen Dank.
Grüße von CopWorker1
Einloggen, um Attachments anzusehen!
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 20.10.20 15:51 
Und wo tritt welcher Fehler auf? NdrGetBuffer sehe ich dort nirgends.

PS: Kleinere Codepassagen kannst (und solltest) du demnächst direkt innerhalb von Code-Tags posten.
CopWorker1 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 20.10.20 16:03 
Hallo,

wenn ich vom C# Client (Endpunkt: 2000) zum C++ Server (Endpunkt: 2000) eine Message schicken will
dann wird folgender Fehler geworfen: CSharpTest.Net.RpcLibrary.RpcException: "Der Authentifizierungsdienst ist unbekannt"
Der Server muss also existent sein.
Der Fehler ist aber immer der gleiche, egal ob beim C++ Server eine Authentifizierung vorgenommen wird oder nicht.

Läuft der Server nicht, dann wird folgender Fehler geworfen: CSharpTest.Net.RpcLibrary.RpcException: "Der RPC-Server ist nicht verfügbar".
Ergibt erstmal einen Sinn.

Momentan habe ich gar keine Ahnung wo ich noch ansetzen soll.
Ich habe schon beide Projekte C++ und C# auf UNICODE geprüft.
Beide Projekte mit der gleichen GUID, Protokoll, Rechnername und Authentifizierungsparametern ausgeführt.

Wie gesagt.
Alle Projekte die in C++ geschrieben sind, kommunizieren untereinander. Bestens.
Auch alle Projekte die in C# geschrieben sind, kommunizieren untereinander. Bestens.
Eine Kommunikation unter C++ und C# Prozessen kommt nicht zu Stande.

Vielen Dank.
Grüße von CopWorker1
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 20.10.20 17:52 
Hast du denn mal in dem C#-Client überprüft, ob die Funktionen selbst fehlerfrei durchlaufen (d.h. den Rückgabewert ausgewertet)?
ausblenden C#-Quelltext
1:
int num = (int) RpcClientApi.RpcBindingSetAuthInfo2(handle.Handle, serverPrincipalName, level, authType, IntPtr.Zero, 0U);					

Hier solltest du mal num auswerten, ob entsprechend der Doku zu RpcBindingSetAuthInfoW RPC_S_OK zurückgegeben wird (sollte wohl den Wert 0 besitzen) - oder eben RPC_S_UNKNOWN_AUTHN_SERVICE.

Evtl. paßt dann einfach das Marshalling nicht (d.h. die Datentypen der Parameter).
CopWorker1 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mi 21.10.20 07:58 
Hallo Th69,

das geht ja bei der Initialisierung des Clients von Statten.
Da bekomme ich 0 = RPC_S_OK als Rückgabewert.
Siehe hierzu "BindingSetAuthInfo2_Return_1.jpg"

Das gleiche Ergebnis im Projekt welches in C++ geschrieben ist.
Siehe hierzu "C++BindingSetAuthInfo2_Return.jpg";

Worin besteht jetzt der Unterschied ob ich anschließend mit einem Server (in C++ geschrieben), oder mit einem Server (in C# geschrieben) kommunizieren will.

Was mich an der ganzen Sache wundert:
Die Projekte in C++, da kommunizieren die Server und Client nicht mehr miteinander wenn eine Authentifizierung vorgenommen wird. Nur wenn keine Authentifizierung vorgenommen wurde.
Die Projekte in C#, da kommunizieren die Server und Client nicht mehr miteinander wenn die Authentifizierung nicht vorgenommen wird. Nur wenn eine Authentifizierung vorgenommen wurde.

Grüße CopWorker1
Einloggen, um Attachments anzusehen!
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 21.10.20 08:48 
Da mußt du mal in beiden Projekten (jeweils Client und Server) schauen, ob sie alle mit denselben Funktionen und Parametern aufgerufen werden (wahrscheinlich gibt es irgendeinen "kleinen" Unterschied bzgl. der Authentifizierung).
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 21.10.20 15:47 
Nicht das ich wirklich helfen könnte aber es ist so das du den Fehler "Der Authentifizierungsdienst ist unbekannt" auch erhältst wenn du gar keine Authentifizierung nutzt?

Es hilft möglicherweise sich mit dem Debugging von MSRPC Connections auseinander zu setzen. Windows scheint da was zu haben. docs.microsoft.com/e...iew-of-rpc-debugging
Da fehlt mir aber jegliche Erfahrung. Kämme nie auf die Idee noch MSRPC zu verwenden ;)
CopWorker1 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Do 22.10.20 13:19 
user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
Da mußt du mal in beiden Projekten (jeweils Client und Server) schauen, ob sie alle mit denselben Funktionen und Parametern aufgerufen werden (wahrscheinlich gibt es irgendeinen "kleinen" Unterschied bzgl. der Authentifizierung).


Daraufhin habe ich die C++ Projekte und C# Projekte geprüft.
Bei beiden werden die in meinem Beitrag erwähnten Funktionen
mit exakt den geleichen Parametern aufgerufen.

Beim Server:
RpcServerRegisterIf(,,); RpcServerUseProtseqEpW(,,); RpcServerRegisterAuthInfoW(,,,);

Beim Client:
RpcStringBindingComposeW(,,,,); RpcBindingFromStringBindingW(,); RpcBindingSetAuthInfoW(,,,,);

Allen Funktionen werden ohne Fehler ausgeführt. Return 0.
Ändert sich leider nichts.

Vielleicht ist gerade das der Fehler, dass die C# Projekte andere Parameter
beim Aufruf der Funktionen benötigen.
Ergibt irgendwie keinen Sinn.

Das einzige was die beiden Projekttypen unterscheiden:
C++ ist "unmanaged code" und C# ist "managed code".
Ich denke dazwischen liegt die Hürde.
Erfolgt da die Kommunikation auch in 2 verschiedenen Ebenen. Keine Ahnung.

Ich verwende MSRPC nur weil uns noch die meisten Prozesse in C++ geschrieben zur Verfügung stehen.
Die alle auf C# umzuschreiben wäre ein Aufwand von 2 MJ (1 Mann, 2 Jahre o. 2 Mann, 1 Jahr).

Ok, wenn jemand noch was weiß
darf er sich gerne hier wieder melden.
Ich schaue jeden Tag mehrmals rein.

Vielen Dank.
Grüße von CopWorker1
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 22.10.20 15:34 
Bei einem RPC Call (wie bei jedem Remoting Verfahren) sollte es uninteressant sein wie die Internas an den Enden des Kanals aussehen solange sie den Kanal gleich benutzen. Es wird einen Unterschied geben den man nur finden muss. Wo wir wieder beim debuggen wären. Wenn du an der Verwendung an den Enden des Kanals keinen Unterschied siehst solltest du versuchen zu schauen was auf dem Kanal stattfindet.

Alternative die du noch hast wäre den C++ Code in managed C++ zu kapseln und so in deinem .Net Projekt zu nutzen.
CopWorker1 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Fr 23.10.20 10:42 
Hallo Ralf Jansen,

jetzt habe ich mal die DLLs der beiden Projekttypen durchforstet.
Ganz tief drin in der Kiste laufen die Request der Client anders ab.

Beim C++ Projekt:
ausblenden volle Höhe C++-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
///              /* [in] */   /* [in] */  /* [size_is][ref][in] */ 
void RpcClientWriteStub(  WORD wCmdId, WORD wSize, BYTE __RPC_FAR pCmdBuffer[])
{
  RPC_BINDING_HANDLE _Handle = 0;
  RPC_MESSAGE _RpcMessage;
  MIDL_STUB_MESSAGE _StubMsg;

  
  RpcTryFinally
  {
    NdrClientInitializeNew( ( PRPC_MESSAGE  )&_RpcMessage, ( PMIDL_STUB_MESSAGE  )&_StubMsg, ( PMIDL_STUB_DESC  )&RpcClientWrite_StubDesc, 0);

    _Handle = hRpcClientWrite;
    _StubMsg.BufferLength = 2U + 2U + 4U;
    _StubMsg.MaxCount = wSize;

    NdrConformantArrayBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg, (unsigned char __RPC_FAR *)pCmdBuffer, (PFORMAT_STRING) &__MIDLTypeFormatString.Format[0] );
    NdrGetBuffer( (PMIDL_STUB_MESSAGE) &_StubMsg, _StubMsg.BufferLength, _Handle );

    *(( WORD __RPC_FAR * )_StubMsg.Buffer)++ = wCmdId;
    *(( WORD __RPC_FAR * )_StubMsg.Buffer)++ = wSize;
    _StubMsg.MaxCount = wSize;

    NdrConformantArrayMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg, (unsigned char __RPC_FAR *)pCmdBuffer, (PFORMAT_STRING) &__MIDLTypeFormatString.Format[0] );
    NdrSendReceive( (PMIDL_STUB_MESSAGE) &_StubMsg, (unsigned char __RPC_FAR *) _StubMsg.Buffer );
  }
  RpcFinally
  {
    NdrFreeBuffer( (PMIDL_STUB_MESSAGE) &_StubMsg );
  }
  RpcEndFinally
}


Beim C# Projekt:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
[DllImport("Rpcrt4.dll", EntryPoint = "NdrClientCall2", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
        private static extern IntPtr NdrClientCall2x86( IntPtr pMIDL_STUB_DESC, IntPtr formatString, IntPtr args);

        [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
        private static byte[] InvokeRpc(RpcHandle handle, Guid iid, byte[] input)
        {
            Ptr<MIDL_STUB_DESC> ptr1;

            if (!handle.GetPtr<Ptr<MIDL_STUB_DESC>>(out ptr1))
                ptr1 = handle.CreatePtr<MIDL_STUB_DESC>(new MIDL_STUB_DESC(handle, handle.Pin<RPC_CLIENT_INTERFACE>(new RPC_CLIENT_INTERFACE(iid)), RpcApi.TYPE_FORMAT, false));

            int ResponseSize = 0;
            IntPtr Response;
            IntPtr num;

            using (Ptr<byte[]> ptr2 = new Ptr<byte[]>(input))
            {
                using (Ptr<int[]> ptr3 = new Ptr<int[]>(new int[10]))
                {
                    ptr3.Data[0] = handle.Handle.ToInt32();
                    ptr3.Data[1] = input.Length;
                    ptr3.Data[2] = ptr2.Handle.ToInt32();
                    ptr3.Data[3] = ptr3.Handle.ToInt32() + 24;
                    ptr3.Data[4] = ptr3.Handle.ToInt32() + 32;
                    ptr3.Data[5] = 0;
                    ptr3.Data[6] = 0;
                    ptr3.Data[8] = 0;

                    try
                    {
                      num = RpcClientApi.NdrClientCall2x86(ptr1.Handle, RpcApi.FUNC_FORMAT_PTR.Handle, ptr3.Handle);
                    }
                    catch (SEHException ex)
                    {
                      // ISSUE: reference to a compiler-generated method
                      RpcException.Assert(ex.ErrorCode);
                      throw;
                    }

                    ResponseSize = ptr3.Data[6];
                    Response = new IntPtr(ptr3.Data[8]);
                }

                GC.KeepAlive((object) ptr2);
            }

            // ISSUE: reference to a compiler-generated method
            RpcException.Assert(num.ToInt32());
            byte[] destination = new byte[ResponseSize];

            if (ResponseSize > 0 && Response != IntPtr.Zero)
                Marshal.Copy(Response, destination, 0, destination.Length);

            RpcApi.Free(Response);
            return destination;

        }


Folgendes:
Wenn ich vom C++ Client zum C# Server einen Request absetzen will kommt es an der
Funktion "NdrGetBuffer( (PMIDL_STUB_MESSAGE) &_StubMsg, _StubMsg.BufferLength, _Handle );" zum Absturz.

Kann es sein, dass die Inhalte der Request einer passenden Formatierung unterzogen werden müssen.
Es sind bei beiden Projekttypen Formatierungsparameter erforderlich (rot markiert).

Bei C++:
NdrConformantArrayBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg, (unsigned char __RPC_FAR *)pCmdBuffer, (PFORMAT_STRING) &__MIDLTypeFormatString.Format[0] );

Bei C#:
num = RpcClientApi.NdrClientCall2x86(ptr1.Handle, RpcApi.FUNC_FORMAT_PTR.Handle, ptr3.Handle);

Leider habe ich es nicht geschafft die Funktionen der C++ DLL in die C# DLL zu portieren.

Vielen Dank.
Grüße von CopWorker1
CopWorker1 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Do 29.10.20 14:32 
Hallo zusammen,

jetzt bin ich endlich einen Schritt weiter.

Jetzt ist es mir gelungen vom C# Prozess zu C++ Prozess eine Kommunikation herzustellen.
Es werden auch die Bytes die ich am Client (C#) verschicke im Server (C++) entgegengenommen.
Der Eventhandler wird angesprungen, sodass ich die Daten auslesen kann. Einfach genial.

Was ich gemacht habe?

Die Authentifizierung bei den C++ Client wie folgt ausgeführt:
ausblenden C++
1:
lRpcStatus = RpcBindingSetAuthInfoW(hRpcClientWrite, (RPC_WSTR)pszNetworkAddress, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_AUTHN_WINNT, nullptr, NULL);					

Die Authentifizierung bei den C++ Server wie folgt ausgeführt:
ausblenden C++
1:
fRpcStatus = RpcServerRegisterAuthInfoW((RPC_WSTR)pszNetworkAddress, RPC_C_AUTHN_WINNT, NULL, nullptr);					

Dann die Interface GUID und die Transfer GUID hartcodiert sowohl bei den C++ - als auch bei den C# - Clients mit den selben Werten eingestellt.


Jetzt geht noch eins nicht:
Ich kann zwar von einem C++ Client zu einem C# Server einen Verbindungsaufbau starten.
Im TCP_Viewer wird sogar eine erfolgreiche Kommunikation aufgezeichnet.
Gesendete und empfangene Datenpakete von Client und Server sehen gut aus.
Auch gibt mir die Funktion beim C++ Client
ausblenden C++
1:
NdrSendReceive( (PMIDL_STUB_MESSAGE) &_StubMsg, (unsigned char __RPC_FAR *) _StubMsg.Buffer );					
keine Fehlermeldung zurück und es führt auch an dieser Stelle zu keinem Absturz mehr.

Leider springt mir der Debugger nach allem in Exception Handling "RpcException(1)" rein.
Anschließend lese ich den RpcExceptionCode() aus. Der besagt dann folgendes:
ausblenden Error
1:
RpcExceptionCode = 1783 (Das Stub erhielt falsche Daten.)					

Die Datenformate sind aber nach den gleichen Strukturen aufgebaut wie die vom C# Client zum C++ Server.

Fast am Ziel oder noch meilenweit davon entfernt?

Ich bedanke mich im Voraus für jeden Tipp.

Mit freundlichen Grüßen
CopWorker1

Moderiert von user profile iconTh69: Code-Tags hinzugefügt
CopWorker1 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 10.11.20 09:25 
Hallo zusammen,

da mein C++ Projekt eigentlich schon stark an Lebenszeit zugenommen hat
habe ich mich entschlossen, dies zu aktualisieren.
Zumindest mal was RPC - Schnittstellen anbetrifft.

In mein C++ Projekt habe ich die Funktion "NdrClientCall2(,,)" eingebunden.
Diese Funktion bereitet mir der MIDL - Compiler vor.

Jetzt weiß ich nicht wie ich den Parameter 3 (IDL_handle) zusammenstellen soll.
In dem "IDL_handle" sollte das Handle vom Client-Interface und das Handle auf die zu
übertragende Datenpakete enthalten sein.

ausblenden C++-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
void RpcClientWriteStub( /* [size_is][ref][in] */ unsigned char pCmdBuffer[  ])
{
    handle_t IDL_handle;
    
    NdrClientCall2(
                  ( PMIDL_STUB_DESC  )&RpcClientWrite_StubDesc,
                  (PFORMAT_STRING) &RpcClientWrite__MIDL_ProcFormatString.Format[0],
                  /*( unsigned char * )&IDL_handle);*/
    
}


In C# habe ich das so gelöst:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
using System;
using System.Runtime.InteropServices;

namespace CSharpTest
{
  internal class Ptr<T> : IDisposable
  {
    private readonly GCHandle _handle;
    public Ptr(T data) => this._handle = GCHandle.Alloc((object) data, GCHandleType.Pinned);
    public T Data => (T) this._handle.Target;
    public IntPtr Handle => this._handle.AddrOfPinnedObject();
    public void Dispose() => this._handle.Free();
  }
}


Mit Hilfe dieser Klasse kann ich eine Datenstack zusammenbauen.
Den Handle dieser Instanz übergebe ich als Parameter 3 der Funktion "NdrClientCall2(,,)".

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
[DllImport("Rpcrt4.dll", EntryPoint = "NdrClientCall2", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
private static extern IntPtr NdrClientCall2x86( IntPtr pMIDL_STUB_DESC, IntPtr formatString, IntPtr args);

private static byte[] InvokeRpc(RpcHandle handle, Guid iid, int iCmd, int iLen, byte[] input)
    
using (Ptr<byte[]> ptr2 = new Ptr<byte[]>(input))
{
    using (Ptr<int[]> ptr3 = new Ptr<int[]>(new int[10]))
    {
        ptr3.Data[0] = handle.Handle.ToInt32();
        ptr3.Data[1] = input.Length;
        ptr3.Data[2] = ptr2.Handle.ToInt32();
        ptr3.Data[3] = ptr3.Handle.ToInt32() + 24;
        ptr3.Data[4] = ptr3.Handle.ToInt32() + 32;
        
        num = RpcClientApi.NdrClientCall2x86(ptr1.Handle, RpcApi.FUNC_FORMAT_PTR.Handle, ptr3.Handle);
}


Kann mir jemand sagen wie ich den Pointer (Ptr<T> : IDisposable) in C++ nachbilden?

Vielen Dank für die Hilfe
Grüße von CopWorker1
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 10.11.20 09:54 
In C++ brauchst du doch nur ein Array oder eine Struktur mit den Werten zu erstellen, diese füllen und dann die Adresse davon zu übergeben.
Die Ptr<T>-Klasse brauchst du ja nur für C#, um den "unmanaged" Datenbereich zu verwalten.