c++ to VB.Net IntPtr Strings - c++

Alright so I have this code, and I pass it to an unmanaged dll, to which I only know the exports, and have some sample code. I'm getting back the correct string, but it's followed by garbage bytes.
I'm basically translating code verbatim from a c++ example program that doesn't have this issue. I'm assume there is something fundamental I am missing here, so if anyone could tell me what that is, I'd appreciate it.
Example C++ Code
void CDUKPT_TESTDlg::OnButton4()
{
// TODO: Add your control notification handler code here
unsigned char dataout[1024],tmp[1024],ksn[20],keyval[20];
int nRet,len;
memset(dataout,0,sizeof(dataout));
memset(ksn,0,sizeof(ksn));
memset(keyval,0,sizeof(keyval));
memset(tmp,0,sizeof(tmp));
UpdateData(TRUE);
two_one((unsigned char *)m_strCURKSN.GetBuffer(m_strCURKSN.GetLength()),m_strCURKSN.GetLength(),ksn);
two_one((unsigned char *)m_strMACK.GetBuffer(m_strMACK.GetLength()),m_strMACK.GetLength(),keyval);
two_one((unsigned char *)m_EncryptDat.GetBuffer(m_EncryptDat.GetLength()),m_EncryptDat.GetLength(),dataout);
len=m_EncryptDat.GetLength()/2;
//extern int __stdcall ExtractDat(unsigned char *input,
//unsigned short len,unsigned char *output,unsigned char *key,
//unsigned char *ksn);
nRet=ExtractDat(dataout,len,tmp,keyval,ksn); //External Call
//Good string+bad trailing data comes back in tmp
m_Result=tmp;
UpdateData(FALSE);
}
This code spits out this ܉Òdÿo 
Here is my VB.Net Code
Public Function Encrypt(ByVal inp As String) As String
Dim tmpSB As New StringBuilder
Dim i As Integer
Dim tKsn As Char() = TwoOne(StrCurKsn)
For i = tKsn.Length To 19
tKsn = tKsn + Chr(0)
Next
Dim tMack As Char() = TwoOne(StrMack)
For i = tMack.Length To 19
tMack = tMack + Chr(0)
Next
Dim tEnc As Char() = TwoOne(inp)
For i = tEnc.Length To 1023
tEnc = tEnc + Chr(0)
Next
Dim len As Integer = tEnc.Length / 2
Dim tmpStr(1023) As Char
Array.Clear(tmpStr, 0, 1024)
Dim tmpPtr = Marshal.StringToHGlobalAnsi(tmpStr)
Dim nRet = ExtractDat(tEnc, len, tmpPtr, tMack, tKsn)
tmpStr = Marshal.PtrToStringAnsi(tmpPtr)
Dim tsl = tmpStr.Length
Encrypt = tmpStr
End Function
This code spits this out
܉Òdÿo ålUäÙålUäÙålUäÙålUäÙålUäÙålUäÙålUäÙ
So I get the right string, but it's followed by a repeating string of garbage characters.
I'm hoping I've done something blatantly wrong here, but I've tried pulling the data as bytes, and chars, and converting in many different methods, and I can't seem to get rid of those characters...Also, ExtractDat doesn't return the length of the string(not a problem, as it's not supposed to, which is really annoying).

Turns out the dll was bad, so after I got a fresh compile from the vendor it seemed to work.

Related

Giving unsigned char** a value in C++

I'm really rusty with C++ and pointers and can't figure out a solution to my problem.
Here is the context:
I have to write a DLL to replace an old one and for one of the functions i must follow this signature:
int GetText(unsigned char** outBuf, unsigned int* outLen);
In the final piece of software, the value of outBuf is displayed in a textbox.
If i understand correctly, outBuf is a pointer to a pointer, or a pointer to char array.
outLen seems to be the length of the data i provide to this buffer.
To test out this function, i'd like to create from scratch a char array and pass it to outBuf.
What i tried so far:
int GetText(unsigned char** outBuf, unsigned int* outLen){
*outBuf = NULL;
*outLen = 0;
//Create a char array from scratch, just to test...
unsigned char text[] = "Hello";
//outLen is the size of text
*outLen = sizeof(text);
//I allocate size to outBuf
*outBuf = new unsigned char[*outLen];
//I copy value of text into outBuf
memcpy(*outBuf, &text, *outLen);
return OK;
};
Is my code to give value to *outBuf and *outLen correct and what could lead it to not working? Because when i try it with the piece of software i was given to test the dll, it fails. It displays a dialog saying Reading failed with status 0.
The function seems to go through as the return value(status) is taken in account. But it doesn't manage to display anything. As if one of the variables i return is empty or null...
here is an extract from the final software (in VB) calling the function. As i'm not allowed to disclose the real code, i changed some value callings:
'lance la lecture
StatusInt = LectureText(NumText, textStr
If StatusInt = 0 Then
'traitement des sauts de ligne
textStr= Replace(textStr, Chr(&HD) + Chr(&HA), Chr(&HA))
textStr= Replace(textStr, Chr(&HA), Chr(&HD) + Chr(&HA))
'copie dans la textbox
Text1.Text = textStr
Else
MsgBox "Lecture failed with err " & Str(StatusInt)
End If
And the function
Public Function LectureText(ByVal NumText, ByRef Text As String) As Long
Dim AddrText As Long
'Dim TextAs String
Dim LengthText As Long
Dim status As Long
'lecture du text
status = GetText(AddrText, LengthText)
'si lecture ok, copie et lib�re le buffer
If status = 0 And LengthText <> 0 Then
'Alloue l'espace n�cessaire pour le text
Text = String(LengthText, vbNullChar)
'copie du text
CopyMemory ByVal Text, ByVal AddrText, LengthText
End If
'retourne status
LectureText= status
End Function
As you can see, if you provide a status = 0, it should not call the dialog saying there is an error. But in my case, it says "Lecture failed with err 0". How is it even possible...
i'm sure it's not the correct way to make things but i don't usually work with C++ and need to spend as little time as possible on this problem. I already searched for 2 days would need to take many things back from the start about C++. Thing i can't offer now.
Thanks in advance for your kind help
The code i wrote was correct.
The fact is my functions needed to be declared with __stdcall to be compatible with VB.
But when compiling the dll with __stdcall, Visual Studio was adding decoration to function names and the existing software in VB was trying to call them by their undecorated names.
So i added a definition file (.def) to my project so that the function names are exported correctly.

How to Convert Data structure to convert char* in c++

I'm think pointer is 4Byte or(2Byte) heap memory allocated
I need Structure data convert to char* Just need 12byte convert
this is my code
please Contact me.
thank you
struct MyData {
unsigned int myNumber;
float x;
float y;
};
int main(){
Mydata* mydata = new Mydata();
mydata->userNumber = 188242268;
mydata->x = 100.0f;
mydata->y = 102.0f;
char* sender = (char*)&mydata;
sioclient->send(sender);
// SocketIO Server Send
}
I don't think what you are asking is possible. string doesn't like having null characters in itself, which would be necessary to directly send the data (For example, a int(1) would have 1 NULL (0x0) character (modern systems would have 3 NULL characters) and 1 0x1 character, which string wouldn't like the null and terminate the string there).
I think you should find another networking library for what you are doing if you can't use WebSocket and need to have the efficiency of sending the bytes of a struct. (Boost::asio perhaps?)
But if you HAVE to use Cocos2d-x SIOClient without the WebSocket, then in the sending side, create a string with the values separated by commas:
string sendMe = to_string(mydata->userNumber) + "," + to_string(mydata->x) + "," + to_string(mydata->y);
And then on the receiving side:
Mydata receiver;
string recStr;//Received string
string temp;
int stage = 0;
for (int itr = 0; itr < temp.length(); itr++)
{
if (recStr[itr] == ',')
{
if (stage==0)
receiver.myNumber = stoi(temp);
else if (stage==1)
receiver.x = stof(temp);
stage++;
temp = "";
}
else
temp += recStr[itr];
}
receiver.y = stof(temp);
Hope that helps.
The old answer, in case you want to switch and have a solution:
Ok, try using the overloaded function
void send (const unsigned char * binaryMsg, unsigned int len);
instead. read about it here
This should look something like the following:
sioclient->send(reinterpret_cast<unsigned char*>(mydata), sizeof(MyData));
Tell me if you are using a different version of Cocos2d-x and thus this doesn't work, or if it failed to solve the problem. When I tried this, it compiled nicely and seemed to behave correctly.
If your compiler doesn't like unsigned char* for a const unsigned char* parameter, just add a const_cast.
Also, remember to delete (mydata); when you are done with it.

How to check the contents of a LPTSTR string?

I'm trying to understand why a segmentation fault (SIGSEGV) occurs during the execution of this piece of code. This error occurs when testing the condition specified in the while instruction, but it does not occur at the first iteration, but at the second iteration.
LPTSTR arrayStr[STR_COUNT];
LPTSTR inputStr;
LPTSTR str;
// calls a function from external library
// in order to set the inputStr string
set_input_str(param1, (char*)&inputStr, param3);
str = inputStr;
while( *str != '\0' )
{
if( debug )
printf("String[%d]: %s\n", i, (char*)str);
arrayStr[i] = str;
str = str + strlen((char*)str) + 1;
i++;
}
After reading this answer, I have done some research on the internet and found this article, so I tried to modify the above code, using this piece of code read in this article (see below). However, this change did not solve the problem.
for (LPTSTR pszz = pszzStart; *pszz; pszz += lstrlen(pszz) + 1) {
... do something with pszz ...
}
As assumed in this answer, it seems that the code expects double null terminated arrays of string. Therefore, I wonder how I could check the contents of the inputStr string, in order to check if it actually contains only one null terminator char.
NOTE: the number of characters in the string printed from printf instruction is twice the value returned by the lstrlen(str) function call at the first iteration.
OK, now that you've included the rest of the code it is clear that it is indeed meant to parse a set of consecutive strings. The problem is that you're mixing narrow and wide string types. All you need to do to fix it is change the variable definitions (and remove the casts):
char *arrayStr[STR_COUNT];
char *inputStr;
char *str;
// calls a function from external library
// in order to set the inputStr string
set_input_str(param1, &inputStr, param3);
str = inputStr;
while( *str != '\0' )
{
if( debug )
printf("String[%d]: %s\n", i, str);
arrayStr[i] = str;
str = str + strlen(str) + 1;
i++;
}
Specifically, the issue was occurring on this line:
while( *str != '\0' )
since you hadn't cast str to char * the comparison was looking for a wide nul rather than a narrow nul.
str = str + strlen(str) + 1;
You go out of bounds, change to
str = str + 1;
or simply:
str++;
Of course you are inconsistently using TSTR and strlen, the latter assuming TCHAR = char
In any case, strlen returns the length of the string, which is the number of characters it contains not including the nul character.
Your arithmetic is out by one but you know you have to add one to the length of the string when you allocate the buffer.
Here however you are starting at position 0 and adding the length which means you are at position len which is the length of the string. Now the string runs from offset 0 to offset len - 1 and offset len holds the null character. Offset len + 1 is out of bounds.
Sometimes you might get away with reading it, if there is extra padding, but it is undefined behaviour and here you got a segfault.
This looks to me like code that expects double null terminated arrays of strings. I suspect that you are passing a single null terminated string.
So you are using something like this:
const char* inputStr = "blah";
but the code expects two null terminators. Such as:
const char* inputStr = "blah\0";
or perhaps an input value with multiple strings:
const char* inputStr = "foo\0bar\0";
Note that these final two strings are indeed double null terminated. Although only one null terminator is written explicitly at the end of the string, the compiler adds another one implicitly.
Your question edit throws a new spanner in the works? The cast in
strlen((char*)str)
is massively dubious. If you need to cast then the cast must be wrong. One wonders what LPTSTR expands to for you. Presumably it expands to wchar_t* since you added that cast to make the code compile. And if so, then the cast does no good. You are lying to the compiler (str is not char*) and lying to the compiler never ends well.
The reason for the segmentation fault is already given by Alter's answer. However, I'd like to add that the usual style of parsing a C-style string is more elegant and less verbose
while (char ch = *str++)
{
// other instructions
// ...
}
The scope of ch is only within in the body of the loop.
Aside: Either tag the question as C or C++ but not both, they're different languages.

convert c++ to vb.net

i have this cpp code that i need an equvalent in vb.net or at leat know what its doing so i can figure out a conversion myself
const char * CResult::strnchr(const char *str, int len, char c) const
{
if (!str)
return NULL;
const char *p = str;
while (len > 0)
{
if (!*p)
return NULL;
if (*p == c)
return p;
p++;
len--;
}
return NULL;
}
and this one
memcmp(prevprev, "ANY", 3)
thank you
strnchr -- Find a character in a length limited string
See this. You can do the same thing in VB.net using String.IndexOf, e.g.
Dim myString As String = "ABCDE"
Dim myInteger As Integer
myInteger = myString.IndexOf("D") ' myInteger = 3
Example copied from MSDN.
strnchr finds the location of the first occurrence of char c in string str. It returns a pointer to the character, which you cannot do in VB.Net, the closest you can do is get the offset of the character from the start of the string.
memcmp(prevprev, "ANY", 3) compares the three letters of "ANY" to the memory location at prevprev, effectively checking that prevprev contains a substring of ANY.
In VB.Net the first can be accomplished with the IndexOf member of the String type.
The second you need to use SubString (again a member on the String type) to create a sub string of the string and check is it equal to "ANY".
Dim myString As String = "Any Hello World"
Dim AnyAtStart As Boolean = myString.SubString(0, 3) = "ANY") ' Will be true '
Dim AnyAtSecond As Boolean = myString.SubString(1, 3) = "ANY") ' Will be false '
Finding VB.NET analogs or closely corresponding functions for many standard C functions is relatively simple using MSDN. Take memcmp() as example:
- MSDN source memcmp, wmemcmp - "Compare characters in two buffers."
- Find strings' comparison method in VB.NET - String.Compare Method (String, String)
But copying C source function by function into VB.NET can produce a strangely ineffective code for relatively small programs. And you will be puzzled every time looking for replacement of raw pointers used everywhere in C programs.
P.S. And what would you do if your ::strnchr will be called differently from standard C function strnchr() - "Find a character in a string."?

Why am i getting two different strings?

I wrote a very simple encryption program to practice c++ and i came across this weird behavior. When i convert my char* array to a string by setting the string equal to the array, then i get a wrong string, however when i create an empty string and add append the chars in the array individually, it creates the correct string. Could someone please explain why this is happening, i just started programming in c++ last week and i cannot figure out why this is not working.
Btw i checked online and these are apparently both valid ways of converting a char array to a string.
void expandPassword(string* pass)
{
int pHash = hashCode(pass);
int pLen = pass->size();
char* expPass = new char[264];
for (int i = 0; i < 264; i++)
{
expPass[i] = (*pass)[i % pLen] * (char) rand();
}
string str;
for (int i = 0; i < 264; i++)
{
str += expPass[i];// This creates the string version correctly
}
string str2 = expPass;// This creates much shorter string
cout <<str<<"\n--------------\n"<<str2<<"\n---------------\n";
delete[] expPass;
}
EDIT: I removed all of the zeros from the array and it did not change anything
When copying from char* to std::string, the assignment operator stops when it reaches the first NULL character. This points to a problem with your "encryption" which is causing embedded NULL characters.
This is one of the main reasons why encoding is used with encrypted data. After encryption, the resulting data should be encoded using Hex/base16 or base64 algorithms.
a c-string as what you are constructing is a series of characters ending with a \0 (zero) ascii value.
in the case of
expPass[i] = (*pass)[i % pLen] * (char) rand();
you may be inserting \0 into the array if the expression evaluates to 0, as well as you do not append a \0 at the end of the string either to assure it being a valid c-string.
when you do
string str2 = expPass;
it can very well be that the string gets shorter since it gets truncated when it finds a \0 somewhere in the string.
This is because str2 = expPass interprets expPass as a C-style string, meaning that a zero-valued ("null") byte '\0' indicates the end of the string. So, for example, this:
char p[2];
p[0] = 'a';
p[1] = '\0';
std::string s = p;
will cause s to have length 1, since p has only one nonzero byte before its terminating '\0'. But this:
char p[2];
p[0] = 'a';
p[1] = '\0';
std::string s;
s += p[0];
s += p[1];
will cause s to have length 2, because it explicitly adds both bytes to s. (A std::string, unlike a C-style string, can contain actual null bytes — though it's not always a good idea to take advantage of that.)
I guess the following line cuts your string:
expPass[i] = (*pass)[i % pLen] * (char) rand();
If rand() returns 0 you get a string terminator at position i.