Wrong behaviour when passing string from c# to c dll - c#

I researched a lot about my problem and found many questions relative to [how to pass string from c# to c dll] :
Passing strings from C# to C++ DLL and back -- minimal example
https://www.codeproject.com/Articles/1189085/%2FArticles%2F1189085%2FPassing-strings-between-managed-and-unmanaged-code
But none of them couldn't help me. Any way I prefer to ask my question :
Briefly explanation :
My c function working properly in c# just when I interchange the GetProcessIntegrityLevel parameters (both in c dll and also in c# import-dll) from :
BOOL GetProcessIntegrityLevel(DWORD dwPID, LPSTR szIntegrityLevel);
To this one :
BOOL GetProcessIntegrityLevel(LPSTR szIntegrityLevel, DWORD dwPID);
In 1st state my program working properly and changes the LPSTR szIntegrityLevel But in 2nd, It doesn't work and LPSTR szIntegrityLevel is always empty with any pid.
I created a c dll library in which I declared the following c function that get Integrity Level of a process through a pid :
#define MAX_INTEGRITY_LEVEL_LENGTH 30
extern "C"
{
__declspec(dllexport) BOOL GetProcessIntegrityLevel(DWORD dwPID, LPSTR szIntegrityLevel);
}
C function implementation :
BOOL GetProcessIntegrityLevel(DWORD dwPID, LPSTR szIntegrityLevel)
{
BOOL bFlag = FALSE; // Return flag
HANDLE hToken = INVALID_HANDLE_VALUE; // Token handle
HANDLE hProcess = NULL; // Process handle
BOOL bProcToken = FALSE; // OpenProcessToken() result
BOOL bTokenInfo = FALSE; // GetTokenInformation() result
DWORD dwLengthNeeded = 0; // Token information length
DWORD dwError = ERROR_SUCCESS; // GetTokenInformation() last error
DWORD dwIntegrityLevel = 0; // Integrity level
PTOKEN_MANDATORY_LABEL pTIL = NULL; // Use as token information
// Open the process
hProcess = OpenProcess(MAXIMUM_ALLOWED | PROCESS_QUERY_LIMITED_INFORMATION,
FALSE, dwPID);
if (hProcess != NULL)
{
// Open process token
bProcToken = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
if (bProcToken == TRUE)
{
// Get token information
bTokenInfo = GetTokenInformation(hToken, TokenIntegrityLevel,
NULL, 0, &dwLengthNeeded);
if (bTokenInfo == FALSE)
{
dwError = GetLastError();
if (dwError == ERROR_INSUFFICIENT_BUFFER)
{
pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwLengthNeeded);
if (pTIL != NULL)
{
// Get token information
bTokenInfo = GetTokenInformation(hToken, TokenIntegrityLevel,
pTIL, dwLengthNeeded, &dwLengthNeeded);
if (bTokenInfo == TRUE)
{
// Get integrity level
dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid,
(DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid) - 1));
if (dwIntegrityLevel <= SECURITY_MANDATORY_LOW_RID)
{
// Low Integrity
StrCpyA(szIntegrityLevel, "Low");
}
else if ((dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID) &&
(dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID))
{
// Medium Integrity
StrCpyA(szIntegrityLevel, "Medium");
}
else if ((dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) &&
(dwIntegrityLevel < SECURITY_MANDATORY_SYSTEM_RID))
{
// High Integrity
StrCpyA(szIntegrityLevel, "High");
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_SYSTEM_RID)
{
// System Integrity
StrCpyA(szIntegrityLevel, "System");
}
else if (dwIntegrityLevel == SECURITY_MANDATORY_UNTRUSTED_RID)
{
// Untrusted integrity
StrCpyA(szIntegrityLevel, "Untrusted");
}
else
{
StrCpyA(szIntegrityLevel, "UnKnown");
}
bFlag = TRUE;
}
LocalFree(pTIL);
}
}
}
// Close token handle
CloseHandle(hToken);
}
// Close the process handle
CloseHandle(hProcess);
}
return bFlag;
}
So, I import GetProcessIntegrityLevel() from my c dll in c# as following :
// Define function pointers for using of c dll functions
[DllImport("ProcessesPropDll.dll",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.Bool)]
// Get integrity level
static extern bool GetProcessIntegrityLevel(ulong dwPID, StringBuilder szIntegrityLevel);
And call the function in c# like this :
// Integrity level
StringBuilder integrityLevel = new StringBuilder(200);
if(GetProcessIntegrityLevel(11684, integrityLevel) == true)
{
MessageBox.Show(integrityLevel.ToString());
}
In this state when i run the program, the GetProcessIntegrityLevel() returns true but integrityLevel is always empty in messagebox for any pid!!!!
‌Surprisingly, when I interchange the parameters in my c function and also in c#, It does work :
__declspec(dllexport) BOOL GetProcessIntegrityLevel(LPSTR szIntegrityLevel, DWORD dwPID);
This is very strange for me. Also I tried with MarshalAs(UnmanagedType.LPStr)] but give me the same result.

In C# ulong is a 64 bit type. The PID parameter is DWORD which is a 32 bit parameter.
Change your C# parameter declaration from ulong to uint to fix the problem.

Related

Global hook for WH_GETMESSAGE hooks only to one application (VisualStudio)

I have a C# application that calls an external DLL file for the hook process.
The hook process simply 'hijacks' key presses, converting lowercase characters into uppercase. I thought it was working only to find out that only VisualStudio gets hooked successfully. Other applications like chrome and explorer does not seem to perform the hook process. Is there anything I missed from creating global hooks?
Any help is greatly appreciated.
dllmain.cpp file:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <stdio.h>
#include <ctime>
#pragma data_seg("Shared")
HHOOK hkKey = NULL;
HINSTANCE hInstHookDll = NULL; //our global variable to store the instance of our DLL
#pragma data_seg() //end of our data segment
#pragma comment(linker,"/section:Shared,rws")
__declspec(dllexport) LRESULT CALLBACK procCharMsg(int nCode, WPARAM wParam, LPARAM lParam)
//this is the hook procedure
{
MSG* msg;
char charCode;
if (nCode >= 0 && nCode == HC_ACTION)
{
msg = (MSG*)lParam;
if (msg->message == WM_CHAR)
{
charCode = msg->wParam;
if (IsCharLower(charCode))
//we check if the character pressed is a small letter
{
//if so, make it to capital letter
charCode -= 32;
msg->wParam = (WPARAM)charCode;
//overwrite the msg structure's wparam
//with our new value.
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
//passing this message to target application
}
extern "C" __declspec(dllexport) void __stdcall SetHook()
{
if (hkKey == NULL)
hkKey = SetWindowsHookEx(WH_GETMESSAGE, procCharMsg, hInstHookDll, 0); // initialize global hook
}
//remove the hook
extern "C" __declspec(dllexport) void __stdcall RemoveHook()
{
if (hkKey != NULL)
UnhookWindowsHookEx(hkKey);
hkKey = NULL;
}
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
switch (Reason)
{
case DLL_PROCESS_ATTACH:
//we initialize our variable with the value that is passed to us
hInstHookDll = (HINSTANCE)hDLL;
break;
case DLL_PROCESS_DETACH:
RemoveHook();
break;
default:
break;
}
return TRUE;
}
main app function that calls the hook from dll file:
IntPtr hInstance = IntPtr.Zero;
IntPtr hProc = IntPtr.Zero;
private delegate void HookSetting();
public void SetHook()
{
hInstance = LoadLibrary("Dll1");
if (IntPtr.Zero == hInstance)
{
// null check
}
hProc = GetProcAddress(hInstance, "_SetHook#0");
if(IntPtr.Zero == hProc)
{
// null check
}
HookSetting hookset = (HookSetting)Marshal.GetDelegateForFunctionPointer(hProc, typeof(HookSetting));
hookset();
}

Convert IntPtr to char** in C#

I'd like to interpret the output of the following unmanaged function:
afc_error_t afc_get_device_info (afc_client_t client, char ***device_information)
I import the dll with the code:
[DllImport("libimobiledevice.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern short afc_get_device_info(IntPtr client, out IntPtr info);
As long as I only needed to convert response to string Marshal.PtrToStringAnsi was okay. However I have no idea how to convert that IntPtr back to char array.
It should be something like:
IntPtr di;
int result = afc_read_directory(client, #"C:\", out di);
if (di == IntPtr.Zero)
{
throw new Exception();
}
IntPtr di2 = di;
while (true)
{
IntPtr ptr = Marshal.ReadIntPtr(di2);
if (ptr == IntPtr.Zero)
{
break;
}
string str = Marshal.PtrToStringAnsi(ptr);
if (str == string.Empty)
{
break;
}
di2 = di2 + IntPtr.Size;
}
Try if it works, then I'll explain how...
important you are leaking memory here...
I've found this example in C:
char **dirs = NULL;
afc_read_directory(afc, "/eafaedf", &dirs);
if (!dirs)
afc_read_directory(afc, "/", &dirs);
printf("Directory time.\n");
for (i = 0; dirs[i]; i++) {
printf("/%s\n", dirs[i]);
free(dirs[i]);
}
if (dirs)
free(dirs);
you are responsible for freeing the memory (see the free inside the cycle and the final free?). In this case (and for other methods that return arrays of C-strings you can use afc_dictionary_free. Note that other methods like afc_receive_data that return a single block of memory you can't use it.

C# Firewall, delete specific entry

I am currently programming a windows-firewallmanager for a company.
Problem is, that I can only delete an entry by name and not by an INetFwRule object or something.
There are entries, that have the same name two times where one is for TCP and the other one for UDP and we might want to delete only one of them.
I could delete both and create one of them afterwards again, but I would not like to use that workaround.
Does anyone have an easy solution to this?
You can only delete rules by name using the INetFwRules interface which seems to be a badly designed API because different rules can have the same name. A workaround is to filter the rules not only by name by also by the other properties that specifies the rule you want to delete. When you have found the rule to delete you can then rename the rule to a unique name using the INetFwRule interface.
You can then delete the rule using this unique temporary name.
Based on #"Martin Liversage" suggesting, here is a working C++ example tested with C# interop.
"AddAppFirewallRule" will only add the firewall rule if it doesn't exist.
"RemoveAppFirewallRule" will remove all firewall rules that match the exe path.
C/C++
#include "pch.h"
#include <windows.h>
#include <stdio.h>
#include <netfw.h>
#include <atlcomcli.h>
#include "Exports.h"
HRESULT WFCOMInitialize(INetFwPolicy2** ppNetFwPolicy2)
{
return CoCreateInstance(__uuidof(NetFwPolicy2), nullptr, CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2), (void**)ppNetFwPolicy2);
}
extern "C"
{
MyFrameworkOSNative_EXPORT int MyFrameworkOSNative_AddAppFirewallRule(int privateNetworks, int publicNetworks, int domainNetworks, wchar_t* exePath, wchar_t* name, wchar_t* groupName, wchar_t* desc, wchar_t* ports, int tcp, int udp)
{
// declare locals
int result = 0;
HRESULT addRuleResult;
BSTR ruleName = SysAllocString(name);
BSTR ruleGroup = SysAllocString(groupName);
BSTR ruleDesc = SysAllocString(desc);
BSTR ruleExe = SysAllocString(exePath);
BSTR rulePorts = nullptr;
if (ports != nullptr) rulePorts = SysAllocString(ports);
INetFwPolicy2* policy = nullptr;
INetFwRules* rules = nullptr;
INetFwRule* rule = nullptr;
long profilesBitMask = 0;
HRESULT iterateResult = 0;
IUnknown* rulesCollection = nullptr;
IEnumVARIANT* variant = nullptr;
CComVariant var = {};
ULONG fetched = 0;
bool found = false;
// init
if (FAILED(WFCOMInitialize(&policy))) goto Cleanup;
if (FAILED(policy->get_Rules(&rules))) goto Cleanup;
//if (FAILED(policy->get_CurrentProfileTypes(&profilesBitMask))) goto Cleanup;
if (privateNetworks) profilesBitMask |= NET_FW_PROFILE2_PRIVATE;
if (publicNetworks) profilesBitMask |= NET_FW_PROFILE2_PUBLIC;
if (domainNetworks) profilesBitMask |= NET_FW_PROFILE2_DOMAIN;
if (FAILED(CoCreateInstance(__uuidof(NetFwRule), nullptr, CLSCTX_INPROC_SERVER, __uuidof(INetFwRule), (void**)&rule))) goto Cleanup;
// setup rule
rule->put_Name(ruleName);
rule->put_Description(ruleDesc);
rule->put_ApplicationName(ruleExe);
if (tcp && udp) rule->put_Protocol(NET_FW_IP_PROTOCOL_ANY);
else if (tcp) rule->put_Protocol(NET_FW_IP_PROTOCOL_TCP);
else if (udp) rule->put_Protocol(NET_FW_IP_PROTOCOL_UDP);
if (rulePorts != nullptr) rule->put_LocalPorts(rulePorts);
rule->put_Direction(NET_FW_RULE_DIR_MAX);
rule->put_Grouping(ruleGroup);
rule->put_Profiles(profilesBitMask);
rule->put_Action(NET_FW_ACTION_ALLOW);
rule->put_Enabled(VARIANT_TRUE);
// get rules enumerator
if (FAILED(rules->get__NewEnum(&rulesCollection))) goto Cleanup;
if (FAILED(rulesCollection->QueryInterface(__uuidof(IEnumVARIANT), (void**)&variant))) goto Cleanup;
// enumerate rules to check if it already exists
var.Clear();
iterateResult = variant->Next(1, &var, &fetched);
while (SUCCEEDED(iterateResult) && iterateResult != S_FALSE)
{
BSTR ruleEXEPath = nullptr;
INetFwRule* existingRule = nullptr;
long exitingRuleProfileBitMask = 0;
if (FAILED((V_DISPATCH(&var))->QueryInterface(__uuidof(INetFwRule), reinterpret_cast<void**>(&existingRule)))) goto Cleanup;
if (FAILED(existingRule->get_ApplicationName(&ruleEXEPath))) goto Cleanup;
if (FAILED(existingRule->get_Profiles(&exitingRuleProfileBitMask))) goto Cleanup;
if (ruleEXEPath != nullptr && wcscmp(ruleEXEPath, exePath) == 0 && exitingRuleProfileBitMask == profilesBitMask)// check if exe paths match
{
BSTR existingRuleName = nullptr;
if (SUCCEEDED(existingRule->get_Name(&existingRuleName)))
{
if (existingRuleName != nullptr)
{
if (wcscmp(ruleName, existingRuleName) == 0) found = true;
SysFreeString(existingRuleName);
}
}
}
// cleanup iteration
if (existingRule != nullptr)
{
existingRule->Release();
existingRule = nullptr;
}
if (ruleEXEPath != nullptr) SysFreeString(ruleEXEPath);
// exit loop if found
if (found) break;
// get next item in collection
var.Clear();
iterateResult = variant->Next(1, &var, &fetched);
}
// add rule if it doesn't already exist
if (!found)
{
addRuleResult = rules->Add(rule);
if (FAILED(addRuleResult)) goto Cleanup;
}
result = 1;// success
// cleanup resources
Cleanup:;
if (variant != nullptr) variant->Release();
if (rulesCollection != nullptr) rulesCollection->Release();
if (ruleName != nullptr) SysFreeString(ruleName);
if (ruleGroup != nullptr) SysFreeString(ruleGroup);
if (ruleDesc != nullptr) SysFreeString(ruleDesc);
if (ruleExe != nullptr) SysFreeString(ruleExe);
if (rulePorts != nullptr) SysFreeString(rulePorts);
if (rule != nullptr) rule->Release();
if (rules != nullptr) rules->Release();
if (policy != nullptr) policy->Release();
return result;
}
MyFrameworkOSNative_EXPORT int MyFrameworkOSNative_RemoveAppFirewallRule(wchar_t* exePath)
{
// declare locals
int result = 0;
INetFwPolicy2* policy = nullptr;
INetFwRules* rules = nullptr;
INetFwRule* rule = nullptr;
long profilesBitMask = 0;
HRESULT iterateResult = 0;
IUnknown* rulesCollection = nullptr;
IEnumVARIANT* variant = nullptr;
CComVariant var = {};
ULONG fetched = 0;
bool found = false;
// init
if (FAILED(WFCOMInitialize(&policy))) goto Cleanup;
if (FAILED(policy->get_Rules(&rules))) goto Cleanup;
// get rules enumerator
if (FAILED(rules->get__NewEnum(&rulesCollection))) goto Cleanup;
if (FAILED(rulesCollection->QueryInterface(__uuidof(IEnumVARIANT), (void**)&variant))) goto Cleanup;
// enumerate rules
var.Clear();
iterateResult = variant->Next(1, &var, &fetched);
while (SUCCEEDED(iterateResult) && iterateResult != S_FALSE)
{
BSTR ruleEXEPath = nullptr;
if (FAILED((V_DISPATCH(&var))->QueryInterface(__uuidof(INetFwRule), reinterpret_cast<void**>(&rule)))) goto Cleanup;
if (FAILED(rule->get_ApplicationName(&ruleEXEPath))) goto Cleanup;
if (ruleEXEPath != nullptr && wcscmp(ruleEXEPath, exePath) == 0)// check if exe paths match
{
found = true;
SysFreeString(ruleEXEPath);
BSTR ruleName = nullptr;
if (FAILED(rule->get_Name(&ruleName)))
{
if (ruleName != nullptr) SysFreeString(ruleName);
goto Cleanup;
}
if (FAILED(rules->Remove(ruleName)))
{
if (ruleName != nullptr) SysFreeString(ruleName);
goto Cleanup;
}
if (ruleName != nullptr) SysFreeString(ruleName);
// get next item in collection
var.Clear();
iterateResult = variant->Next(1, &var, &fetched);
continue;// continue to scan for more rules with same criteria
}
// cleanup iteration
if (rule != nullptr)
{
rule->Release();
rule = nullptr;
}
if (ruleEXEPath != nullptr) SysFreeString(ruleEXEPath);
// get next item in collection
var.Clear();
iterateResult = variant->Next(1, &var, &fetched);
}
if (!found) goto Cleanup;
result = 1;// success
// cleanup resources
Cleanup:;
if (variant != nullptr) variant->Release();
if (rulesCollection != nullptr) rulesCollection->Release();
if (rule != nullptr) rule->Release();
if (rules != nullptr) rules->Release();
if (policy != nullptr) policy->Release();
return result;
}
}
C#
[DllImport("MyFramework.OS.Native.dll")]
private static unsafe extern int VMyFrameworkOSNative_AddAppFirewallRule(int privateNetworks, int publicNetworks, int domainNetworks, char* exePath, char* name, char* groupName, char* desc, char* ports, int tcp, int udp);
[DllImport("MyFramework.OS.Native.dll")]
private static unsafe extern int MyFrameworkOSNative_RemoveAppFirewallRule(char* exePath);
public static unsafe bool AddAppFirewallRule(bool privateNetworks, bool publicNetworks, bool domainNetworks, string exePath, string ruleName, string ruleDesc, int port = -1, bool tcp = true, bool udp = true)
{
// ensure COM is init
Ole32.CoInitialize(IntPtr.Zero);
// invoke native method
string portValue = port.ToString();
fixed (char* exePathPtr = exePath)
fixed (char* ruleNamePtr = ruleName)
fixed (char* ruleDescPtr = ruleDesc)
fixed (char* portValuePtr = portValue)
{
return MyFrameworkOSNative_AddAppFirewallRule
(
privateNetworks ? 1 : 0,
publicNetworks ? 1 : 0,
domainNetworks ? 1 : 0,
exePathPtr,
ruleNamePtr, ruleNamePtr,
ruleDescPtr,
port > 0 ? portValuePtr : null,
tcp ? 1 : 0, udp ? 1 : 0
) != 0;
}
}
public static unsafe bool RemoveAppFirewallRule(string exePath)
{
// ensure COM is init
Ole32.CoInitialize(IntPtr.Zero);
// invoke native method
fixed (char* exePathPtr = exePath)
{
return VMyFrameworkOSNative_RemoveAppFirewallRule(exePathPtr) != 0;
}
}
UnitTests
[Fact]
public void AddAppFirewallRule()
{
using (var lib = new LibHandle("MyFramework.OS.Native.dll"))
{
Assert.True(NetworkUtils.AddAppFirewallRule(true, true, false, #"<Path-To-Exe>", "TestRule", "Test Rule Desc"));
}
}
[Fact]
public void RemoveAppFirewallRule()
{
using (var lib = new LibHandle("MyFramework.OS.Native.dll"))
{
Assert.True(NetworkUtils.RemoveAppFirewallRule(#"<Path-To-Exe>"));
}
}
public static void RemoveFirewallRules(string RuleName = "BreakermindCom")
{
try
{
Type tNetFwPolicy2 = Type.GetTypeFromProgID("HNetCfg.FwPolicy2");
INetFwPolicy2 fwPolicy2 = (INetFwPolicy2)Activator.CreateInstance(tNetFwPolicy2);
var currentProfiles = fwPolicy2.CurrentProfileTypes;
// Lista rules
// List<INetFwRule> RuleList = new List<INetFwRule>();
foreach (INetFwRule rule in fwPolicy2.Rules)
{
// Add rule to list
// RuleList.Add(rule);
// Console.WriteLine(rule.Name);
if (rule.Name.IndexOf(RuleName) != -1)
{
// Now add the rule
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
firewallPolicy.Rules.Remove(rule.Name);
Console.WriteLine(rule.Name + " has been deleted from Firewall Policy");
}
}
}
catch (Exception r)
{
Console.WriteLine("Error delete rule from firewall");
}}
Look at this

CreateRemoteThread says file doesn't exist, but it DOES exist

I am trying to inject a .dll into another process's memory, by using Interop.
This is my C# code:
class Program
{
static void Main(string[] args)
{
var result = Inject(Process.GetProcessesByName("notepad")[0].Id);
Console.WriteLine(result);
if (result < 0)
throw new Win32Exception(Marshal.GetLastWin32Error());
Console.ReadLine();
}
[DllImport("Testing.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Inject(int dwProcessId);
}
The code for the function Inject is this (notice the comment on return -6):
//C++ .dll that does actually exists
const char* DLL_NAME = "C:\\Users\\Bruno\\Source\\Repos\\CourseGuidance\\InteropTesting\Debug\\Loader.dll";
TESTING_API DWORD Inject(DWORD dwProcessId)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (hProcess == NULL)
return -1;
HMODULE hModule = GetModuleHandleW(L"kernel32.dll");
if (hModule == NULL)
return -2;
FARPROC pLoadLibrary = GetProcAddress(hModule, "LoadLibraryA");
if (pLoadLibrary == NULL)
return -3;
LPVOID pMemory = VirtualAllocEx(hProcess, NULL, strlen(DLL_NAME) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pMemory == NULL)
return -4;
BOOL result = WriteProcessMemory(hProcess, pMemory, DLL_NAME, strlen(DLL_NAME) + 1, NULL);
if (!result)
return -5;
HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE) pLoadLibrary, pMemory, 0, NULL);
if (hThread == NULL)
return -6;
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(hProcess, pMemory, strlen(DLL_NAME) + 1, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return 0;
}
I think the error I am getting might be misleading, since the file does exist in that folder. I also thought the error could be because of LoadLibraryA, which is for ASCII, even tried using LoadLibraryW, but I still got the same issue.
If someone has an idea of what could be wrong, could you provide me the right direction?
You did not declare Inject as SetLastError=true. Therefore, the value you got from Marshal.GetLastWin32Error is garbage:
Marshal.GetLastWin32Error Method
Returns the error code returned by the last unmanaged function that
was called using platform invoke that has the
DllImportAttribute.SetLastError flag set.
You can use this method to obtain error codes only if you apply the
System.Runtime.InteropServices.DllImportAttribute to the method
signature and set the SetLastError field to true. The process for this
varies depending upon the source language used: C# and C++ are false
by default, but the Declare statement in Visual Basic is true.

Pinvoke C# from C++ dll using DLLimport in C#

C++ Function header in DLL this two function to get some information about the wifi stations around me using win mobile 6.5 device and i need to invoke them to use them in C# code
// (adapter names , pointer to destination buffer ,and the size , returned structs)
bool __declspec(dllexport) GetBBSIDs(LPWSTR pAdapter, struct BSSIDInfo *pDest, DWORD &dwBufSizeBytes, DWORD &dwReturnedItems);
bool __declspec(dllexport) RefreshBSSIDs(LPWSTR pAdapter);
bool __declspec(dllexport) GetAdapters(LPWSTR pDest, DWORD &dwBufSizeBytes);
C# sample
[DllImport(#"\Storage Card\Work\Beaad.dll", EntryPoint = "GetAdapters", SetLastError = true)]
public static extern bool getAdapters([MarshalAs(UnmanagedType.LPWStr)] String buf, ref UInt32 dwBufSizeBytes);
[DllImport(#"\Storage Card\Work\Beaad.dll", EntryPoint = "RefreshBSSIDs", SetLastError = true)]
public static extern bool refreshBSSIDs([MarshalAs(UnmanagedType.LPWStr)]String buf);
[DllImport(#"\Storage Card\Work\Beaad.dll", EntryPoint = "GetBBSIDs", SetLastError = true)]
public static extern bool getBBSIDs([MarshalAs(UnmanagedType.LPWStr)]String buf,BSSIDInfo [] nfo, ref UInt32 dwBufSizeBytes, ref UInt32 dwReturnedItems);
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]
public struct BSSIDInfo
{
public byte[] BSSID; //mac
public char[] SSID;
public BSSIDInfo(byte[]bs,char[] ss)
{
this.RSSI = 0;
this.Infastructure = 0;
this.Channel = 0;
this.Auth = 0;
bs = new byte[6];
ss = new char[32];
BSSID = bs;
SSID = ss;
}
public int RSSI;
public int Channel;
public int Infastructure;
public int Auth;
}
public static byte[] StrToByteArray(string str)
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
return encoding.GetBytes(str);
}
public static char[] c = new char[1024];
string buf = new string(c);
public void button1_Click(object sender, EventArgs e)
{
BSSIDInfo[] nfo = new BSSIDInfo[128];
byte[] bytee=StrToByteArray(buf);
UInt32 dwsize= new UInt32();
UInt32 dwTmp = new UInt32();
UInt32 dwCount = new UInt32();
dwTmp = Convert.ToUInt32(Marshal.SizeOf(typeof(BSSIDInfo)) * nfo.Length);
dwCount =0;
dwsize=Convert.ToUInt32(bytee.Length);
if (false == getAdapters(buf,ref dwsize) || dwsize == 0)
{
label1.Text = "no adabters";
}
else
{
String [] strList=new String[15];
if (buf.Contains(',') == false)// one adapter
{
textBox1.Text = buf;
}
else
{
strList = buf.Split(',');
for (int i = 0; i < strList.Length; i++)
{
textBox1.Text+= strList[i]+Environment.NewLine;
}
}
if (refreshBSSIDs(buf) && getBBSIDs(buf, nfo, ref dwTmp, ref dwCount) && dwCount > 0)
{
//refreshBSSIDs(buf) &&
for (int i = 0; i < dwCount; i++)
{
textBox2.Text += nfo.GetValue(i).ToString() + Environment.NewLine;
}
}
else
{
//make another thing
}
}
}
and when i put this dll on the mobile and the C# app.exe the first function that named as Getadapters(..) return to me the name of the adapter in the first textbox1 then the app stopped and give me not supported exception when the mobile tries to execute the other two function that named as refreshBSSID() and getBSSIDs() so what is the problem ? or is there another solution to get this information (BSSID ,SS ..etc) ?
C++ by default unless changed uses a caller( Cdecl ) calling convention. Your C++ code does not change the calling convention. Your C# code by default ( unless you change it ) will use a callee convention ( StdCall ).
While this might not be exactly the problem your having it still is technically incorrect. Even if you were to fix your current problem you likely will end up having a problem because of the calling convention.
I am going to guess your C# BSSIDInfo structure does not match the C++ structure. Why do the method StrToByteArray when all it does is GetBytes on the given string...
when the mobile tries to execute the
other two function that named as
refreshBSSID() and getBSSIDs() so what
is the problem ? or is there another
solution to get this information
I thought I knew the reason took another look and I was wrong.

Categories

Resources