private static string ValueTypeData(VALUE_DATA_TYPE type, int dataSize, byte[] data)
        {
            string dataStr = string.Empty;

            try
            {
                switch (type)
                {
                case VALUE_DATA_TYPE.REG_BINARY:
                {
                    //maximum data size to 256;
                    for (int i = 0; i < 256; i++)
                    {
                        if (i >= dataSize)
                        {
                            break;
                        }

                        dataStr += string.Format("0x{0:x2}", data[i]);
                    }

                    break;
                }

                case VALUE_DATA_TYPE.REG_DWORD:
                {
                    uint value = BitConverter.ToUInt32(data, 0);
                    dataStr = string.Format("0x{0:x8}({1})", value, value);
                    break;
                }

                case VALUE_DATA_TYPE.REG_DWORD_BIG_ENDIAN:
                {
                    //A 4-byte numerical value whose least significant byte is at the highest address
                    byte leastByte  = data[3];
                    byte secondByte = data[2];
                    data[3] = data[0];
                    data[2] = data[1];
                    data[1] = secondByte;
                    data[0] = leastByte;

                    uint value = BitConverter.ToUInt32(data, 0);
                    dataStr = string.Format("0x{0:x8}({1})", value, value);

                    break;
                }

                case VALUE_DATA_TYPE.REG_EXPAND_SZ:
                {
                    //A null-terminated Unicode string, containing unexpanded references to environment variables, such as "%PATH%"
                    dataStr = Encoding.Unicode.GetString(data, 0, dataSize).Replace("\0", "");
                    break;
                }

                case VALUE_DATA_TYPE.REG_MULTI_SZ:
                {
                    //An array of null-terminated strings, terminated by another zero
                    dataStr = Encoding.Unicode.GetString(data, 0, dataSize).Replace("\0", "");
                    break;
                }

                case VALUE_DATA_TYPE.REG_SZ:
                {
                    //A null-terminated Unicode string
                    dataStr = Encoding.Unicode.GetString(data, 0, dataSize).Replace("\0", "");
                    break;
                }

                case VALUE_DATA_TYPE.REG_QWORD:
                {
                    UInt64 value = BitConverter.ToUInt64(data, 0);
                    dataStr = string.Format("0x{0:x16}({1})", value, value);
                    break;
                }

                default: break;
                }
            }
            catch (Exception ex)
            {
                dataStr = "get data failed:" + ex.Message;
            }


            return(dataStr);
        }
        public static string FormatDescription(FilterAPI.MessageSendData messageSend)
        {
            string descrption = string.Empty;

            FilterAPI.RegCallbackClass regCallbackClass = (FilterAPI.RegCallbackClass)messageSend.Offset;

            try
            {
                if (messageSend.Status != (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS)
                {
                    return("");
                }

                switch (regCallbackClass)
                {
                case FilterAPI.RegCallbackClass.Reg_Pre_Delete_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Delete_Key:
                {
                    descrption = "registry key is being deleted.";
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Set_Value_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Set_Value_Key:
                {
                    VALUE_DATA_TYPE valueType = (VALUE_DATA_TYPE)messageSend.InfoClass;
                    descrption  = "Type:" + valueType.ToString();
                    descrption += " Data:" + ValueTypeData(valueType, (int)messageSend.DataBufferLength, messageSend.DataBuffer);
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Delete_Value_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Delete_Value_Key:
                {
                    descrption = "registry key's value is being deleted.";
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_SetInformation_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_SetInformation_Key:
                {
                    KEY_SET_INFORMATION_CLASS keySetInformationClass = (KEY_SET_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keySetInformationClass.ToString();
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Rename_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Rename_Key:
                {
                    string newName = Encoding.Unicode.GetString(messageSend.DataBuffer);
                    descrption = "registry key's name is being changed to " + newName;
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Enumerate_Key:
                {
                    KEY_INFORMATION_CLASS keyInformationClass = (KEY_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keyInformationClass.ToString();

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Enumerate_Key:
                {
                    KEY_INFORMATION_CLASS keyInformationClass = (KEY_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption += KeyInformation(keyInformationClass, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Enumerate_Value_Key:
                {
                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keyValuseInformationClass.ToString();

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Enumerate_Value_Key:
                {
                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption += KeyValueInformation(keyValuseInformationClass, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Query_Key:
                {
                    KEY_INFORMATION_CLASS keyInformationClass = (KEY_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keyInformationClass.ToString();

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Query_Key:
                {
                    KEY_INFORMATION_CLASS keyInformationClass = (KEY_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption += KeyInformation(keyInformationClass, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Query_Value_Key:
                {
                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption = keyValuseInformationClass.ToString();

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Query_Value_Key:
                {
                    //for unit test
                    if (messageSend.FileName.IndexOf("EaseFilter") > 0)
                    {
                        //this is our test key.
                        RegistryUnitTest.postQueryValueKeyPassed = true;
                    }

                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    descrption += KeyValueInformation(keyValuseInformationClass, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Query_Multiple_Value_Key:
                {
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Post_Query_Multiple_Value_Key:
                {
                    uint entryCount = messageSend.InfoClass;

                    MemoryStream ms = new MemoryStream(messageSend.DataBuffer);
                    BinaryReader br = new BinaryReader(ms);

                    for (int i = 0; i < entryCount && ms.Position < ms.Length; i++)
                    {
                        long   currentOffset   = ms.Position;
                        int    nextEntryOffset = br.ReadInt32();
                        int    valueNameLength = br.ReadInt32();
                        int    dataType        = br.ReadInt32();
                        int    dataLength      = br.ReadInt32();
                        byte[] valueName       = br.ReadBytes(valueNameLength);
                        byte[] data            = br.ReadBytes(dataLength);

                        VALUE_DATA_TYPE type = (VALUE_DATA_TYPE)dataType;
                        descrption += "Name:" + Encoding.Unicode.GetString(valueName, 0, valueNameLength);
                        descrption += " Type:" + type.ToString();
                        descrption += " Data:" + ValueTypeData(type, dataLength, data) + Environment.NewLine;

                        ms.Position = currentOffset + nextEntryOffset;
                    }

                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Create_KeyEx:
                case FilterAPI.RegCallbackClass.Reg_Post_Create_KeyEx:
                case FilterAPI.RegCallbackClass.Reg_Pre_Open_KeyEx:
                case FilterAPI.RegCallbackClass.Reg_Post_Open_KeyEx:
                {
                    descrption += FormatCreateDescription(messageSend);
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Load_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Load_Key:
                {
                    descrption += "SourceFile:" + Encoding.Unicode.GetString(messageSend.DataBuffer, 0, (int)messageSend.DataBufferLength);
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Replace_Key:
                case FilterAPI.RegCallbackClass.Reg_Post_Replace_Key:
                {
                    descrption += "NewFileName:" + Encoding.Unicode.GetString(messageSend.DataBuffer, 0, (int)messageSend.DataBufferLength);
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Query_KeyName:
                case FilterAPI.RegCallbackClass.Reg_Post_Query_KeyName:
                {
                    break;
                }

                default: descrption = "unsupported registry callback class:" + regCallbackClass.ToString(); break;
                }
            }
            catch (Exception ex)
            {
                descrption = "Format description failed, return error:" + ex.Message;
            }

            return(descrption);
        }