ListViewItem GetFilterMessage(FilterAPI.MessageSendData messageSend, ref string[] filterMessages)
        {
            ListViewItem lvItem = new ListViewItem();

            try
            {
                string userName    = string.Empty;
                string processName = string.Empty;

                FilterAPI.DecodeUserName(messageSend.Sid, out userName);
                FilterAPI.DecodeProcessName(messageSend.ProcessId, out processName);

                if ((messageSend.CreateOptions & (uint)WinData.CreateOptions.FO_REMOTE_ORIGIN) > 0)
                {
                    //this is the request comes from remote server
                    userName += ",remote access from network.";
                }

                string[] listData = new string[listView_Message.Columns.Count];
                int      col      = 0;
                listData[col++] = messageSend.MessageId.ToString();
                listData[col++] = FormatDateTime(messageSend.TransactionTime);
                listData[col++] = userName;
                listData[col++] = processName + "  (" + messageSend.ProcessId + ")";
                listData[col++] = messageSend.ThreadId.ToString();
                listData[col++] = FormatIOName(messageSend);
                listData[col++] = messageSend.FileObject.ToString("X");
                listData[col++] = messageSend.FileName;
                listData[col++] = messageSend.FileSize.ToString();
                listData[col++] = ((FileAttributes)messageSend.FileAttributes).ToString();
                listData[col++] = FormatDateTime(messageSend.LastWriteTime);
                listData[col++] = FormatStatus(messageSend.Status);
                listData[col++] = FormatDescription(messageSend);

                filterMessages = listData;

                lvItem = new ListViewItem(listData, 0);

                if (messageSend.Status >= (uint)NtStatus.Status.Error)
                {
                    lvItem.BackColor = Color.LightGray;
                    lvItem.ForeColor = Color.Red;
                }
                else if (messageSend.Status > (uint)NtStatus.Status.Warning)
                {
                    lvItem.BackColor = Color.LightGray;
                    lvItem.ForeColor = Color.Yellow;
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(445, "GetFilterMessage", EventLevel.Error, "Add callback message failed." + ex.Message);
                lvItem = null;
            }

            return(lvItem);
        }
        public void AddMessage(FilterAPI.MessageSendData messageSend)
        {
            lock (messageQueue)
            {
                if (messageQueue.Count > GlobalConfig.MaximumFilterMessages)
                {
                    messageQueue.Clear();
                }

                messageQueue.Enqueue(messageSend);
            }

            autoEvent.Set();
        }
        private static string FormatCreateDescription(FilterAPI.MessageSendData messageSend)
        {
            uint createOptions = messageSend.CreateOptions;
            uint desiredAccess = messageSend.DesiredAccess;
            uint dispositions  = messageSend.Disposition;

            string message = string.Empty;

            message += "createOptions:";
            foreach (REG_CREATE_OPTIONS createOption in Enum.GetValues(typeof(REG_CREATE_OPTIONS)))
            {
                if (createOption == (REG_CREATE_OPTIONS)((uint)createOption & createOptions))
                {
                    message += createOption.ToString() + "; ";
                }
            }

            message += "(0x" + createOptions.ToString("X") + ");\r\n";

            message += "desiredAccess:";
            foreach (REG_ACCESS_MASK accessMask in Enum.GetValues(typeof(REG_ACCESS_MASK)))
            {
                if (accessMask == (REG_ACCESS_MASK)((uint)accessMask & desiredAccess))
                {
                    message += accessMask.ToString() + "; ";
                }
            }

            message += "(0x" + desiredAccess.ToString("X") + ");\r\n";

            if (dispositions > 0)
            {
                message += "dispositions:";
                foreach (REG_DISPOSITION disposition in Enum.GetValues(typeof(REG_DISPOSITION)))
                {
                    if (disposition == (REG_DISPOSITION)((uint)disposition & dispositions))
                    {
                        message += disposition.ToString() + "; ";
                    }
                }

                message += "(0x" + desiredAccess.ToString("X") + ");";
            }

            return(message);
        }
        /// <summary>
        /// convert the secure share file's embedded DRM data to encrypted file's meta data with the attached tag.
        /// </summary>
        /// <param name="messageSend"></param>
        private void ProcessSecuredSharedFile(FilterAPI.MessageSendData messageSend)
        {
            string lastError = string.Empty;

            if (!DigitalRightControl.ProcessSecureShareFile(messageSend.FileName, out lastError))
            {
                if (!retryFiles.ContainsKey(messageSend.FileName))
                {
                    retryFiles.Add(messageSend.FileName, 0);
                }

                EventManager.WriteMessage(147, "ProcessSecureShareFile", EventLevel.Error, lastError);
            }
            else
            {
                EventManager.WriteMessage(159, "ProcessSecureShareFile", EventLevel.Verbose, "Process secure file " + messageSend.FileName + " succeeded.");
            }
        }
Exemplo n.º 5
0
        public void AddMessage(FilterAPI.MessageSendData messageSend)
        {
            lock (messageQueue)
            {
                if (messageQueue.Count > GlobalConfig.MaximumFilterMessages)
                {
                    messageQueue.Clear();
                }


                if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_PROCESS_CREATION_INFO ||
                    messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_PROCESS_TERMINATION_INFO ||
                    messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_THREAD_CREATION_INFO ||
                    messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_THREAD_TERMINATION_INFO)
                {
                    //this is the process filter command, we don't display the message.
                    return;
                }

                messageQueue.Enqueue(messageSend);
            }

            autoEvent.Set();
        }
        public static string FormatIOName(FilterAPI.MessageSendData messageSend)
        {
            string ioName = string.Empty;

            try
            {
                if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_FILE_CHANGED_EVENT)
                {
                    foreach (FilterAPI.EVENTTYPE eventType in Enum.GetValues(typeof(FilterAPI.EVENTTYPE)))
                    {
                        if (eventType != FilterAPI.EVENTTYPE.NONE && ((messageSend.InfoClass & (uint)eventType) > 0))
                        {
                            if (ioName.Length > 0)
                            {
                                ioName = ioName + " ," + eventType.ToString();
                            }
                            else
                            {
                                ioName = eventType.ToString();
                            }
                        }
                    }
                }
                else if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_REQUEST_USER_PERMIT ||
                         messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_REQUEST_ENCRYPTION_IV_AND_KEY)
                {
                    ioName = "REQUEST_ACCESS_PERMISSION";
                }
                else if (messageSend.MessageType == (uint)FilterAPI.MessageType.PRE_QUERY_INFORMATION)
                {
                    if (messageSend.FsContext.ToInt64() == 0)
                    {
                        ioName = "PRE_FASTIO_NETWORK_QUERY_OPEN";
                    }
                    else
                    {
                        ioName = "PRE_QUERY_INFORMATION";
                    }
                }
                else if (messageSend.MessageType == (uint)FilterAPI.MessageType.POST_QUERY_INFORMATION)
                {
                    if (messageSend.FsContext.ToInt64() == 0)
                    {
                        ioName = "POST_FASTIO_NETWORK_QUERY_OPEN";
                    }
                    else
                    {
                        ioName = "POST_QUERY_INFORMATION";
                    }
                }
                else
                {
                    ioName = ((FilterAPI.MessageType)messageSend.MessageType).ToString();
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(592, "FormatIOName", EventLevel.Error, "Get IO name from " + messageSend.MessageType.ToString("X") + " exception:" + ex.Message);
            }

            if (ioName.Trim().Length == 0)
            {
                ioName = "UnKnown IO Type (0x" + messageSend.MessageType.ToString("X") + ")";
            }

            return(ioName);
        }
        string FormatDescription(FilterAPI.MessageSendData messageSend)
        {
            string message = string.Empty;

            try
            {
                if (messageSend.Status == (uint)NtStatus.Status.Success)
                {
                    if (messageSend.MessageType == (uint)FilterAPI.FilterCommand.FILTER_SEND_FILE_CHANGED_EVENT &&
                        messageSend.InfoClass == (uint)FilterAPI.EVENTTYPE.RENAMED)
                    {
                        string newFileName = string.Empty;

                        if (messageSend.DataBufferLength > 0)
                        {
                            byte[] buffer = new byte[messageSend.DataBufferLength];
                            Array.Copy(messageSend.DataBuffer, buffer, buffer.Length);
                            newFileName = Encoding.Unicode.GetString(buffer);
                        }

                        message = "File " + messageSend.FileName + " was renamed to " + newFileName;
                        return(message);
                    }
                }
                else
                {
                    return(message);
                }

                switch ((FilterAPI.MessageType)messageSend.MessageType)
                {
                case FilterAPI.MessageType.POST_CREATE:
                {
                    if ((messageSend.CreateOptions & (uint)WinData.CreateOptions.FILE_DELETE_ON_CLOSE) > 0)
                    {
                        message = "file was marked as deleted.";
                    }

                    if (messageSend.Status == (uint)NtStatus.Status.Success)
                    {
                        //the create status is meaningful only when the status is succeeded.
                        message += "CreateStatus:" + ((WinData.CreateStatus)messageSend.CreateStatus).ToString();
                    }

                    message += " DesiredAccess:" + FormatDesiredAccess(messageSend.DesiredAccess);
                    message += " Disposition:" + ((WinData.Disposition)messageSend.Disposition).ToString();
                    message += " ShareAccess:" + ((WinData.ShareAccess)messageSend.SharedAccess).ToString();
                    message += " CreateOptions:" + FormatCreateOptions(messageSend.CreateOptions);

                    break;
                }

                case FilterAPI.MessageType.POST_CACHE_READ:
                case FilterAPI.MessageType.POST_FASTIO_READ:
                case FilterAPI.MessageType.POST_NOCACHE_READ:
                case FilterAPI.MessageType.POST_PAGING_IO_READ:
                {
                    message = "read offset:" + messageSend.Offset + " length:" + messageSend.Length;
                    //read data is here
                    //messageSend.DataBufferLength, messageSend.DataBuffer

                    break;
                }

                case FilterAPI.MessageType.POST_CACHE_WRITE:
                case FilterAPI.MessageType.POST_FASTIO_WRITE:
                case FilterAPI.MessageType.POST_NOCACHE_WRITE:
                case FilterAPI.MessageType.POST_PAGING_IO_WRITE:
                {
                    message = "write offset:" + messageSend.Offset + " length:" + messageSend.Length;
                    //written data is here
                    //messageSend.DataBufferLength, messageSend.DataBuffer

                    break;
                }

                case FilterAPI.MessageType.POST_SET_INFORMATION:
                {
                    message = FormatInformationDataBuffer((WinData.FileInfomationClass)messageSend.InfoClass, messageSend.DataBufferLength, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.MessageType.POST_QUERY_INFORMATION:
                {
                    message = FormatInformationDataBuffer((WinData.FileInfomationClass)messageSend.InfoClass, messageSend.DataBufferLength, messageSend.DataBuffer);

                    break;
                }

                case FilterAPI.MessageType.POST_SET_SECURITY:
                {
                    message = "set security with information class:" + FormatSecurityInfoClass(messageSend.InfoClass);
                    break;
                }

                case FilterAPI.MessageType.POST_QUERY_SECURITY:
                {
                    message = "query security with information class:" + FormatSecurityInfoClass(messageSend.InfoClass);
                    break;
                }

                case FilterAPI.MessageType.POST_DIRECTORY:
                {
                    message = "browse directory with information class:" + ((WinData.FileInfomationClass)messageSend.InfoClass).ToString();
                    break;
                }

                case FilterAPI.MessageType.POST_CLEANUP:
                {
                    message = "all file handles to fileObject " + messageSend.FileObject.ToString("X") + " were closed.";
                    break;
                }

                case FilterAPI.MessageType.POST_CLOSE:
                {
                    message = "all system references to fileObject " + messageSend.FileObject.ToString("X") + " were closed.";
                    break;
                }
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(318, "FormatDescription", EventLevel.Error, "Format description failed with error " + ex.Message);
            }


            return(message);
        }
Exemplo n.º 8
0
        public static bool AuthorizeFileAccess(FilterAPI.MessageSendData messageSend, ref FilterAPI.MessageReplyData messageReply)
        {
            bool ret = true;

            try
            {
                messageReply.MessageId    = messageSend.MessageId;
                messageReply.MessageType  = messageSend.MessageType;
                messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;

                messageReply.MessageId   = messageSend.MessageId;
                messageReply.MessageType = messageSend.MessageType;

                //
                //here you can control all the registered IO requests,block the access or modify the I/O data base on the file IO information from MessageSend struture
                //
                //

                //if you don't want to change anything to this IO request, just let it pass through as below setting:
                //messageReply.FilterStatus = 0;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                //if you want to block the access this IO request before it goes down to the file system, you can return the status as below,
                //it is only for pre IO requests, it means the user IO reuqests will be completed here instead of going down to the file system.
                //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;

                //if you want to modify the IO data and complete the pre IO with your own data, you can return status as below:
                // messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                // messageReply.DataBufferLength = the return data buffer length.
                // messageReply.DataBuffer = the data you want to return.
                // messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                FilterAPI.MessageType       messageType = (FilterAPI.MessageType)messageSend.MessageType;
                WinData.FileInfomationClass infoClass   = (WinData.FileInfomationClass)messageSend.InfoClass;

                uint   dataLength = messageSend.DataBufferLength;
                byte[] data       = messageSend.DataBuffer;

                //here is some IO information for your reference:
                if ((messageSend.CreateOptions & (uint)WinData.CreateOptions.FO_REMOTE_ORIGIN) > 0)
                {
                    //this is file access request comes from remote network server
                }

                //you can check the file create option with this data:
                //"DesiredAccess: messageSend.DesiredAccess
                //"Disposition:" + ((WinData.Disposition)messageSend.Disposition).ToString();
                //"ShareAccess:" + ((WinData.ShareAccess)messageSend.SharedAccess).ToString();
                //"CreateOptions:"messageSend.CreateOptions


                //Here is the demo to copy file content before it was deleted.-----------------------------------------------
                bool isFileDeleting = false;
                if (messageSend.Status == (uint)NtStatus.Status.Success)
                {
                    if (messageType == FilterAPI.MessageType.POST_CREATE)
                    {
                        if ((messageSend.CreateOptions & (uint)WinData.CreateOptions.FILE_DELETE_ON_CLOSE) > 0)
                        {
                            isFileDeleting = true;
                        }
                    }
                    else if (messageType == FilterAPI.MessageType.PRE_SET_INFORMATION)
                    {
                        if (infoClass == WinData.FileInfomationClass.FileDispositionInformation)
                        {
                            isFileDeleting = true;
                        }
                    }

                    if (isFileDeleting)
                    {
                        //IntPtr fileHandle = IntPtr.Zero;
                        //bool retVal = FilterAPI.GetFileHandleInFilter(messageSend.FileName,(uint)FileAccess.Read, ref fileHandle);
                        //if (retVal)
                        //{
                        //    SafeFileHandle sHandle = new SafeFileHandle(fileHandle, true);
                        //    FileStream fileStream = new FileStream(sHandle, FileAccess.Read);

                        //    //copy your data here...

                        //    fileStream.Close();
                        //}
                    }
                }
                //End -----------------------------------------------



                switch (messageType)
                {
                case FilterAPI.MessageType.PRE_CREATE:
                {
                    //here you reparse the file open to another new file name

                    //string newReparseFileName = "\\??\\c:\\myNewFile.txt";
                    //byte[] returnData = Encoding.Unicode.GetBytes(newReparseFileName);
                    //Array.Copy(returnData, messageReply.DataBuffer, returnData.Length);
                    //messageReply.DataBufferLength = (uint)returnData.Length;
                    //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                    //messageReply.ReturnStatus = (uint)NtStatus.Status.Reparse;

                    break;
                }


                case FilterAPI.MessageType.PRE_CACHE_READ:
                case FilterAPI.MessageType.POST_CACHE_READ:
                case FilterAPI.MessageType.PRE_NOCACHE_READ:
                case FilterAPI.MessageType.POST_NOCACHE_READ:
                case FilterAPI.MessageType.PRE_PAGING_IO_READ:
                case FilterAPI.MessageType.POST_PAGING_IO_READ:
                case FilterAPI.MessageType.PRE_CACHE_WRITE:
                case FilterAPI.MessageType.POST_CACHE_WRITE:
                case FilterAPI.MessageType.PRE_NOCACHE_WRITE:
                case FilterAPI.MessageType.POST_NOCACHE_WRITE:
                case FilterAPI.MessageType.PRE_PAGING_IO_WRITE:
                case FilterAPI.MessageType.POST_PAGING_IO_WRITE:
                {
                    //byte[] returnData = //new data you want to modify the read/write data;
                    //Array.Copy(returnData, messageReply.DataBuffer, returnData.Length);
                    //messageReply.DataBufferLength = (uint)returnData.Length;

                    ////for pre IO,use this one
                    //// messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;

                    // messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                    // messageReply.ReturnStatus = (uint)NtStatus.Status.Success;


                    break;
                }

                case FilterAPI.MessageType.PRE_SET_INFORMATION:
                case FilterAPI.MessageType.POST_SET_INFORMATION:
                case FilterAPI.MessageType.PRE_QUERY_INFORMATION:
                case FilterAPI.MessageType.POST_QUERY_INFORMATION:
                {
                    switch (infoClass)
                    {
                    case WinData.FileInfomationClass.FileRenameInformation:
                    {
                        if (FilterAPI.MessageType.PRE_SET_INFORMATION == messageType)
                        {
                            string blockFileName = @"c:\filterTest\blockRename.txt";
                            //test block rename to blockFileName, it needs to register PRE_SET_INFORMATION;
                            if (string.Compare(messageSend.FileName, blockFileName, true) == 0)
                            {
                                EventManager.WriteMessage(179, "IOAccessControl", EventLevel.Warning, "Block rename for file:" + messageSend.FileName);
                                ret = false;
                                break;
                            }
                        }

                        //you can block file rename as below
                        //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;
                        break;
                    }

                    case WinData.FileInfomationClass.FileDispositionInformation:
                    {
                        //you can block file delete as below
                        //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;
                        break;
                    }

                    case WinData.FileInfomationClass.FileEndOfFileInformation:
                    {
                        //change file size
                        break;
                    }

                    case WinData.FileInfomationClass.FileBasicInformation:
                    {
                        //file basic information
                        break;
                    }

                    case WinData.FileInfomationClass.FileStandardInformation:
                    {
                        //file standard information
                        break;
                    }

                    case WinData.FileInfomationClass.FileNetworkOpenInformation:
                    {
                        //file network information
                        break;
                    }

                    case WinData.FileInfomationClass.FileInternalInformation:
                    {
                        //file internal inofrmation
                        break;
                    }

                    default:
                    {
                        break;
                    }
                    }

                    break;
                }
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(174, "IOAccessControl", EventLevel.Error, "IOAccessControl failed." + ex.Message);
            }

            return(ret);
        }
Exemplo n.º 9
0
        ListViewItem GetFilterMessage(FilterAPI.MessageSendData messageSend, ref string[] filterMessages)
        {
            ListViewItem lvItem = new ListViewItem();

            try
            {
                string userName    = string.Empty;
                string processName = string.Empty;

                FilterAPI.DecodeUserName(messageSend.Sid, out userName);
                FilterAPI.DecodeProcessName(messageSend.ProcessId, out processName);

                if ((messageSend.CreateOptions & (uint)WinData.CreateOptions.FO_REMOTE_ORIGIN) > 0)
                {
                    //this is the request comes from remote server
                    string remoteIp = string.Empty;
                    if (messageSend.DataBufferLength > 0 && ((uint)FilterAPI.MessageType.POST_CREATE == messageSend.MessageType))
                    {
                        byte[] buffer = new byte[messageSend.DataBufferLength];
                        Array.Copy(messageSend.DataBuffer, buffer, buffer.Length);
                        remoteIp  = Encoding.Unicode.GetString(buffer);
                        userName += ",RemoteIP:" + remoteIp;
                    }
                    else
                    {
                        userName += ",Accessed from remote computer.";
                    }
                }

                string[] listData = new string[listView_Message.Columns.Count];
                int      col      = 0;
                listData[col++] = messageSend.MessageId.ToString();
                listData[col++] = FormatDateTime(messageSend.TransactionTime);
                listData[col++] = userName;
                listData[col++] = processName + "  (" + messageSend.ProcessId + ")";
                listData[col++] = messageSend.ThreadId.ToString();
                listData[col++] = FormatIOName(messageSend);
                listData[col++] = messageSend.FileObject.ToString("X");
                listData[col++] = messageSend.FileName;
                listData[col++] = messageSend.FileSize.ToString();
                listData[col++] = ((FileAttributes)messageSend.FileAttributes).ToString();
                listData[col++] = FormatDateTime(messageSend.LastWriteTime);
                listData[col++] = FormatStatus(messageSend.Status);
                listData[col++] = FormatDescription(messageSend);

                filterMessages = listData;

                lvItem = new ListViewItem(listData, 0);

                if (messageSend.Status >= (uint)NtStatus.Status.Error)
                {
                    lvItem.BackColor = Color.LightGray;
                    lvItem.ForeColor = Color.Red;
                }
                else if (messageSend.Status > (uint)NtStatus.Status.Warning)
                {
                    lvItem.BackColor = Color.LightGray;
                    lvItem.ForeColor = Color.Yellow;
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(445, "GetFilterMessage", EventLevel.Error, "Add callback message failed." + ex.Message);
                lvItem = null;
            }

            return(lvItem);
        }
        public static bool AuthorizeRegistryAccess(FilterAPI.MessageSendData messageSend, ref FilterAPI.MessageReplyData messageReply)
        {
            bool ret = true;

            try
            {
                messageReply.MessageId    = messageSend.MessageId;
                messageReply.MessageType  = messageSend.MessageType;
                messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;


                //
                //here you can control registry request,block the access or modify the registry data.
                //
                //

                //if you don't want to change anything to this registry request, just let it pass through as below setting:
                //messageReply.FilterStatus = 0;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

                //if you want to block the access this registry request, you can return the status as below,
                //it is only for pre callback requests.
                //messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                //messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;

                //if you want to modify the registry data and complete the pre IO with your own data, you can return status as below:
                // messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                // messageReply.DataBufferLength = the return data buffer length.
                // messageReply.DataBuffer = the data you want to return.
                // messageReply.ReturnStatus = (uint)NtStatus.Status.Success;

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

                uint   dataLength = messageSend.DataBufferLength;
                byte[] data       = messageSend.DataBuffer;

                switch (regCallbackClass)
                {
                case FilterAPI.RegCallbackClass.Reg_Pre_Query_Value_Key:
                {
                    KEY_VALUE_INFORMATION_CLASS keyValuseInformationClass = (KEY_VALUE_INFORMATION_CLASS)messageSend.InfoClass;
                    IntPtr keyValueInfoPtr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);


                    if (messageSend.FileName.IndexOf("EaseFilter") <= 0)
                    {
                        //this is not our unit test key
                        break;
                    }

                    //below code is for unit test to demo how to complete pre-callback registry call with our own data.
                    EventManager.WriteMessage(400, "AuthorizeRegistryAccess", EventLevel.Error, "Reg_Pre_Query_Value_Key keyValuseInformationClass:" + keyValuseInformationClass.ToString());

                    switch (keyValuseInformationClass)
                    {
                    case KEY_VALUE_INFORMATION_CLASS.KeyValueBasicInformation:
                    {
                        //public struct KEY_VALUE_BASIC_INFORMATION
                        // {
                        //     public uint TitleIndex;
                        //     public uint Type;
                        //     public uint NameLength;
                        //     public byte[] Name;
                        // }

                        uint   titleIndex      = 0;
                        uint   type            = (uint)VALUE_DATA_TYPE.REG_DWORD;
                        byte[] valueName       = Encoding.Unicode.GetBytes("value1");
                        uint   valueNameLength = (uint)valueName.Length;

                        MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                        BinaryWriter bw = new BinaryWriter(ms);
                        bw.Write(titleIndex);
                        bw.Write(type);
                        bw.Write(valueNameLength);
                        bw.Write(valueName);

                        messageReply.DataBufferLength = (uint)ms.Position;
                        messageReply.FilterStatus     = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;


                        break;
                    }

                    case KEY_VALUE_INFORMATION_CLASS.KeyValueFullInformation:
                    {
                        //KeyValueFullInformation class structure
                        //public uint TitleIndex;
                        //public uint Type;
                        //public uint DataOffset;
                        //public uint DataLength;
                        //public uint NameLength;
                        //public byte[] Name;

                        uint   titleIndex      = 0;
                        uint   type            = (uint)VALUE_DATA_TYPE.REG_DWORD;
                        uint   testData        = 12345;
                        uint   testDataLength  = sizeof(uint);
                        byte[] valueName       = Encoding.Unicode.GetBytes("value1");
                        uint   valueNameLength = (uint)valueName.Length;
                        uint   dataOffset      = 5 * sizeof(uint) + valueNameLength;

                        MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                        BinaryWriter bw = new BinaryWriter(ms);
                        bw.Write(titleIndex);
                        bw.Write(type);
                        bw.Write(dataOffset);
                        bw.Write(testDataLength);
                        bw.Write(valueNameLength);
                        bw.Write(valueName);
                        bw.Write(testData);

                        messageReply.DataBufferLength = (uint)ms.Position;
                        messageReply.FilterStatus     = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;


                        break;
                    }

                    case KEY_VALUE_INFORMATION_CLASS.KeyValuePartialInformation:
                    {
                        // public struct KEY_VALUE_PARTIAL_INFORMATION
                        //{
                        //    public uint TitleIndex;
                        //    public uint Type;
                        //    public uint DataLength;
                        //    public byte[] Data;
                        //}

                        uint titleIndex     = 0;
                        uint type           = (uint)VALUE_DATA_TYPE.REG_DWORD;
                        uint testData       = 12345;
                        uint testDataLength = sizeof(uint);

                        MemoryStream ms = new MemoryStream(messageReply.DataBuffer);
                        BinaryWriter bw = new BinaryWriter(ms);

                        bw.Write(titleIndex);
                        bw.Write(type);
                        bw.Write(testDataLength);
                        bw.Write(testData);

                        messageReply.DataBufferLength = (uint)ms.Position;

                        messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION | (uint)FilterAPI.FilterStatus.FILTER_DATA_BUFFER_IS_UPDATED;
                        messageReply.ReturnStatus = (uint)FilterAPI.NTSTATUS.STATUS_SUCCESS;

                        break;
                    }


                    default: break;
                    }
                    break;
                }

                case FilterAPI.RegCallbackClass.Reg_Pre_Create_KeyEx:
                case FilterAPI.RegCallbackClass.Reg_Pre_Open_KeyEx:
                {
                    //this is our unit test key
                    if (messageSend.FileName.IndexOf("EaseFilter") > 0)
                    {
                        //NOT allow to create new registry key.

                        messageReply.FilterStatus = (uint)FilterAPI.FilterStatus.FILTER_COMPLETE_PRE_OPERATION;
                        messageReply.ReturnStatus = (uint)NtStatus.Status.AccessDenied;
                    }

                    break;
                }

                default: break;
                }
            }
            catch (Exception ex)
            {
                EventManager.WriteMessage(400, "AuthorizeRegistryAccess", EventLevel.Error, "AuthorizeRegistryAccess exception:" + ex.Message);
            }

            return(ret);
        }
        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);
        }