TCITEM (user32)
Last changed: -194.138.39.54

.
Summary
Specifies or receives the attributes of a tab item.

C# Signature:

[StructLayout(LayoutKind.Sequential)]
    struct TCITEM
    {
        public uint mask;
        public int state;
        public int statemask;
        public IntPtr text;
        public int size;
        public int image;
        public int param;
    }

VB Signature:

Declare Function TCITEM Lib "user32.dll" (TODO) As TODO

User-Defined Types:

None.

Alternative Managed API:

Do you know one? Please contribute it!

Notes:

None.

Tips & Tricks:

Please add some!

Sample Code:

I slightly edited some things, so maybe it doesn't work out of the box, should be 99% fine though.

{

    #region code
    TCITEM tcitem = new TCITEM();
    tcitem.size = 200;
    uint ProcessID;
    GetWindowThreadProcessId((IntPtr)handle, out ProcessID);
    IntPtr process = OpenProcess(ProcessAccessFlags.VMOperation | ProcessAccessFlags.VMRead |
    ProcessAccessFlags.VMWrite | ProcessAccessFlags.QueryInformation, false, ProcessID);

    IntPtr pszTextPtr = VirtualAllocEx(process, IntPtr.Zero, 512, AllocationType.Commit, MemoryProtection.ReadWrite);
    IntPtr tcitemPtr = VirtualAllocEx(process, IntPtr.Zero, (uint)Marshal.SizeOf(typeof(TCITEM)), AllocationType.Commit, MemoryProtection.ReadWrite);

    const int TCIF_STATE = 0x10;
    const int TCIF_TEXT = 0x1;
    tcitem.mask = TCIF_STATE | TCIF_TEXT;

    tcitem.text = pszTextPtr;
    string L_buf = "nasenmann ";
    IntPtr TextPtr = Marshal.StringToHGlobalAnsi(L_buf);
    L_buf = "überschrieben";
    int bytesReaded;
    WriteProcessMemory(process, pszTextPtr, TextPtr, 512, IntPtr.Zero);
    Marshal.FreeHGlobal(TextPtr);
    IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(tcitem));
    Marshal.StructureToPtr(tcitem, ptr, true);
    tcitem.size = 1; // überschrieben
    WriteProcessMemory(process, tcitemPtr, ptr, Marshal.SizeOf(tcitem), IntPtr.Zero);
    Marshal.FreeHGlobal(ptr);
    int res = SendMessage(handle, TCM_GETITEMA, index, tcitemPtr);
    ptr = Marshal.AllocHGlobal(512);
    ReadProcessMemory(process, pszTextPtr, ptr, 512, out bytesReaded);
    L_buf = Marshal.PtrToStringAnsi(ptr);
    Marshal.FreeHGlobal(ptr);
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(tcitem));
    ReadProcessMemory(process, tcitemPtr, ptr, (int)Marshal.SizeOf(tcitem), out bytesReaded);
    tcitem = (TCITEM)Marshal.PtrToStructure(ptr, tcitem.GetType());
    Marshal.FreeHGlobal(ptr);
    VirtualFreeEx(process, tcitemPtr, 0, FreeType.Release);
    VirtualFreeEx(process, pszTextPtr, 0, FreeType.Release);

    #endregion

    #region defines
    [Flags]
    public enum FreeType
    {
    Decommit = 0x4000,
    Release = 0x8000,
    }

    [Flags]
    enum ProcessAccessFlags : uint
    {
    All = 0x001F0FFF,
    Terminate = 0x00000001,
    CreateThread = 0x00000002,
    VMOperation = 0x00000008,
    VMRead = 0x00000010,
    VMWrite = 0x00000020,
    DupHandle = 0x00000040,
    SetInformation = 0x00000200,
    QueryInformation = 0x00000400,
    Synchronize = 0x00100000
    }

    [Flags]
    public enum AllocationType
    {
    Commit = 0x1000,
    Reserve = 0x2000,
    Decommit = 0x4000,
    Release = 0x8000,
    Reset = 0x80000,
    Physical = 0x400000,
    TopDown = 0x100000,
    WriteWatch = 0x200000,
    LargePages = 0x20000000
    }

    [Flags]
    public enum MemoryProtection
    {
    Execute = 0x10,
    ExecuteRead = 0x20,
    ExecuteReadWrite = 0x40,
    ExecuteWriteCopy = 0x80,
    NoAccess = 0x01,
    ReadOnly = 0x02,
    ReadWrite = 0x04,
    WriteCopy = 0x08,
    GuardModifierflag = 0x100,
    NoCacheModifierflag = 0x200,
    WriteCombineModifierflag = 0x400
    }

    [DllImport("user32.dll", SetLastError = true)]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
       uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
    [DllImport("kernel32.dll")]
    static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);
    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
       int dwSize, FreeType dwFreeType);
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool ReadProcessMemory(
     IntPtr hProcess,
     IntPtr lpBaseAddress,
    IntPtr lpBuffer,
     int dwSize,
     out int lpNumberOfBytesRead
    );
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int nSize, IntPtr lpNumberOfBytesWritten);
    #endregion

}

You can find some more ideas here: http://www.andreas-reiff.de/2011/06/c-speicher-anderen-prozess-befullen-lassen-checken-ob-ein-button-gedruckt/ (though it is in German)

I am also working on a generic method to pass structs. It is working for an arbitrary number of strings contained in the struct and is very user friendly. Once it is finished I will post it somewhere on the net as well.

Also, you can use the code here for any situation where you have a struct that contains a pointer to some other structure that you then again need to fill (and read).

Documentation
TCITEM on MSDN