开发者

C# - Modify what IntPtr is pointing to (replace a string)

Code:

...

IntPtr buff

...

buff can be pointing to something pretty large. This buff will contain a string, lets say "XYZ123", that I want to replace with "ABC456". Unfortunately, the remainder of data is not a string. This is preventing me from doing something like the following:

..Marshal.PtrToStringAnsi(buff)

//do string replace here

..Marsh开发者_如何学Goal.StringToHGlobalAnsi(..)

As it would screw up the other "non-string" binary data. Given the large size and my inability to do the conversion above, what is the best way to go about doing this?

Do a Marshal.Copy into a byte[] in a loop, looking for a character sequence?

Thanks!


Not Sure I fully understand what you're trying to do. But, since you don't want to mess with the unmanaged buffer, why don't you replace the string in the unmanaged buffer itself without converting it to a managed string (and back)?

As long as the string is delimited by '\0' (standard C string) you can look for the string you want to replace (e.g "XYZ123"). You can do it yourself (walking the string char by char, with pointer arithmetic) or you can even P/invoke

LPTSTR StrStr(          
LPCTSTR lpFirst,
    LPCTSTR lpSrch
);

from shlwapi.dll

Once you find the pointer to the string ("XYZ123") you can replace it by using something like:

LPTSTR StrCpy(
    LPTSTR psz1,
    LPCTSTR psz2
);

or again, implement it yourself.

NOTE: the functions above have safe alternatives. see: Security Considerations: Microsoft Windows Shell

The following example shows how to use unsafe code and IntPtr. It might help:

public unsafe static void Main()
{
    int a = 10;
    Console.WriteLine("a is {0} ({0:X})", a);
    IntPtr ip = new IntPtr(&a);
    byte* pTarget = (byte*)ip.ToPointer() + 1;
    *pTarget = 2;

    Console.WriteLine("a is {0} ({0:X})", a);
}

EDIT: I assumed the two strings are the same length. (As they are in your example)


Given that your byte array is large I would not copy it all the time.
From my point of view you either need to

  • write a C function and call it in the C# code
  • write a compare and a swap function as unsafe C# code similar to the examples from dtroy.

This is some untested code which you may try:

static unsafe Boolean Compare(byte* src, byte * compare, int size)
{
    Boolean result = true;
    int i = 0;
    while (result && i < size)
    {
        result=result&&*(src+i)==*(compare+i);
    }
    return result;
}

static unsafe void Replace (byte* src, byte* newData, int size) {
    for (int i = 0; i < size; i++)
        *(src + i) = *(newData + i);   
}

static unsafe Boolean Swap(IntPtr ptr, byte[] search, byte[] newData, int ptrBytes)
{
    Boolean result = false;
    byte* pSearch =  (byte*) Marshal.UnsafeAddrOfPinnedArrayElement(search, 0);
    byte* pReplace = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(newData, 0);
    for (int i = 0; i < ptrBytes - search.Length;i++ )
    {
        byte* pTarget = (byte*)ptr.ToPointer()+i;
        if (Compare(pTarget, pSearch, search.Length))
        {
            Replace(pTarget, pReplace, newData.Length);
            return true;
        }
    }
    return result;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜