// This overload method is used to get ListView group data.
        internal static unsafe bool GetGroupInfo(IntPtr hwnd, ref NativeMethods.LVGROUP group)
        {
            ProcessorTypes localBitness;
            ProcessorTypes remoteBitness;
            GetProcessTypes(hwnd, out localBitness, out remoteBitness);

            if (localBitness == remoteBitness)
            {
                int result = 0;
                fixed (NativeMethods.LVGROUP* pGroup = &group)
                {
                    result = XSendGetIndex(hwnd, NativeMethods.LVM_GETGROUPINFO,
                                    new IntPtr(group.iGroupID), new IntPtr(pGroup), Marshal.SizeOf(group.GetType()));
                }
                if (result == group.iGroupID)
                {
                    return true;
                }
            }
            else if (remoteBitness == ProcessorTypes.Processor32Bit)
            {
                LVGROUP_32 group32 = new LVGROUP_32(group);
                int result = XSendGetIndex(hwnd, NativeMethods.LVM_GETGROUPINFO,
                                new IntPtr(group.iGroupID), new IntPtr(&group32), Marshal.SizeOf(group32.GetType()));
                if (result == group32.iGroupID)
                {
                    group = (NativeMethods.LVGROUP)group32;
                    return true;
                }
            }
            else if (remoteBitness == ProcessorTypes.Processor64Bit)
            {
                LVGROUP_64 group64 = new LVGROUP_64(group);
                int result = XSendGetIndex(hwnd, NativeMethods.LVM_GETGROUPINFO,
                                new IntPtr(group.iGroupID), new IntPtr(&group64), Marshal.SizeOf(group64.GetType()));
                if (result == group64.iGroupID)
                {
                    group = (NativeMethods.LVGROUP)group64;
                    return true;
                }
            }
            return false;
        }
        // This overload method is used to get ListView Group Item text.
        internal static unsafe string GetItemText(IntPtr hwnd, NativeMethods.LVGROUP item)
        {
            ProcessorTypes localBitness;
            ProcessorTypes remoteBitness;
            GetProcessTypes(hwnd, out localBitness, out remoteBitness);

            if (localBitness == remoteBitness)
            {
                // obtain group string (header only)
                if (Environment.OSVersion.Version.Major == 5)
                {
                    return ListView_V6_GetGroupTextOnWinXp(hwnd, item);
                }

                return GetTextWithinStructure(hwnd, NativeMethods.LVM_GETGROUPINFO, new IntPtr(item.iGroupID), new IntPtr(&item), Marshal.SizeOf(item.GetType()), new IntPtr(&item.pszHeader), item.cchHeader);
            }
            else if (remoteBitness == ProcessorTypes.Processor32Bit)
            {
                LVGROUP_32 item32 = new LVGROUP_32(item);

                // obtain group string (header only)
                if (Environment.OSVersion.Version.Major == 5)
                {
                    return ListView_V6_GetGroupTextOnWinXp(hwnd, item32);
                }

                return GetTextWithinStructure(hwnd, NativeMethods.LVM_GETGROUPINFO, new IntPtr(item32.iGroupID), new IntPtr(&item32), Marshal.SizeOf(item32.GetType()), new IntPtr(&item32.pszHeader), item32.cchHeader);
            }
            else if (remoteBitness == ProcessorTypes.Processor64Bit)
            {
                LVGROUP_64 item64 = new LVGROUP_64(item);

                // obtain group string (header only)
                if (Environment.OSVersion.Version.Major == 5)
                {
                    return ListView_V6_GetGroupTextOnWinXp(hwnd, item64);
                }

                return GetTextWithinStructure(hwnd, NativeMethods.LVM_GETGROUPINFO, new IntPtr(item64.iGroupID), new IntPtr(&item64), Marshal.SizeOf(item64.GetType()), new IntPtr(&item64.pszHeader), item64.cchHeader);
            }
            return "";
        }
        private static string ListView_V6_GetGroupTextOnWinXp(IntPtr hwnd, LVGROUP_32 group)
        {
            // Due to the ListView Group bug on WinXP we need to have a special implementation
            // for retrieving a text of the group for WinXP
            // On WinXP the code to give back the header text looks something like that:
            //            if (plvgrp->mask & LVGF_HEADER)
            //            {
            //                plvgrp->pszHeader = pgrp->pszHeader;
            //            }
            // Instead of something along the lines of StringCchCopy(plvgrp->pszHeader, plvgrp->cchHeader, pgrp->pszHeader);
            // Hence after the call to CommCtrl.Common_GetSetText() we will get back an internal buffer pointer
            // and not the text itself (ref string str will be ""). It makes no sense to call CommCtrl.Common_GetSetText()
            // Use XSendMessage to get the internal buffer pointer and than "manually" read the string

            // get internal buffer pointer (group.pszHeader)
            // NOTE: do no check XSendMessage.XSend since, LVM_GETGROUPINFO returns id of the group which can be 0, hence
            // can be treated as failure
            // We will check group.pszHeader to IntPtr.Zero after the call
            unsafe
            {
                XSend(hwnd, NativeMethods.LVM_GETGROUPINFO, new IntPtr(group.iGroupID), new IntPtr(&group), group.cbSize, ErrorValue.NoCheck);
            }
            if (group.pszHeader != 0)
            {
                // Read the string manually...
                // allocate memory from the unmanaged memory
                using (SafeCoTaskMem copyTo = new SafeCoTaskMem(NativeMethods.MAX_PATH))
                {
                    if (!copyTo.IsInvalid)
                    {
                        using (SafeProcessHandle hProcess = new SafeProcessHandle(hwnd))
                        {
                            if (!hProcess.IsInvalid)
                            {
                                int count;
                                if (Misc.ReadProcessMemory(hProcess, new IntPtr(group.pszHeader), copyTo, new IntPtr(NativeMethods.MAX_PATH), out count))
                                {
                                    return copyTo.GetStringAuto();
                                }
                            }
                        }
                    }
                }
            }

            return "";
        }