private void ParseAuditOperations(ref Rec rec, AuditInfo audit, StringBuilder buffer, StringBuilder domainBuffer, StringBuilder userBuffer, ref int sentItems)
        {
            try
            {
                if (string.IsNullOrEmpty(rec.Description))
                    return;

                using (var reader = new StringReader(rec.Description))
                {
                    string line;
                    var state = -1;

                    var mask = 0;
                    var values = new string[9];

                    while ((line = reader.ReadLine()) != null)
                    {
                        Match m;
                        switch (state)
                        {
                            case -1:
                                m = RegLine.Match(line);
                                if (m.Success)
                                {
                                    for (state = 1; state < m.Groups.Count && !m.Groups[state].Success; ++state)
                                    {
                                    }
                                    if (state == m.Groups.Count)
                                        state = -1;
                                    else
                                        --state;
                                }
                                break;
                            default:
                                m = ((Regex)RegExps[state][0]).Match(line);
                                if (m.Success)
                                {
                                    //WriteLine(line);
                                    var i = 1;
                                    var ms = 1;
                                    while (i < m.Groups.Count)
                                    {
                                        if (m.Groups[i].Success)
                                        {
                                            values[i / 2] = m.Groups[i + 1].Value;
                                            mask |= ms;
                                            break;
                                        }
                                        i += 2;
                                        ms <<= 1;
                                    }
                                    if (mask == ((int)RegExps[state][1]))
                                    {
                                        var username = string.IsNullOrEmpty(values[1]) || string.IsNullOrEmpty(values[2])
                                                       ? UserWithDomain(values[0], buffer, domainBuffer, userBuffer)
                                                       : values[1] + "\\" + values[2];
                                        AuditLogonEnv env;
                                        if (!_handles.TryGetValue(values[3], out env))
                                        {
                                            env = new AuditLogonEnv(values[3]);
                                            _handles[env.LogonId] = env;
                                        }
                                        try
                                        {
                                            switch (state)
                                            {
                                                case 0:
                                                    AuditCloseHandle(ref rec, env, username, values[0], values[4], values[5], values[6], ref sentItems);
                                                    return;
                                                case 1:
                                                    AuditDuplicateHandle(ref rec, env, values[3], username, values[0], values[4], values[5],
                                                                         values[6], values[7], ref sentItems);
                                                    return;
                                                case 2:
                                                    if (audit.ObjectType == "File")
                                                        AuditObjectRequestHandle(ref rec, env, values[3], username, values[0], values[5], values[6],
                                                                                 values[8], values[4], values[7], ref sentItems);
                                                    return;
                                                case 3:
                                                    AuditDeleteHandle(ref rec, env, username, values[0], values[4], values[5], values[6], ref sentItems);
                                                    return;
                                            }
                                        }
                                        finally
                                        {
                                            if (env.Handles.Count == 0)
                                                _handles.Remove(env.LogonId);
                                            //WriteLine("===================================================");
                                        }
                                    }
                                }
                                break;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                L.Log(LogType.FILE, LogLevel.ERROR, "Error while parsing audit operations:" + e);
            }
        }
        private void AuditObjectRequestHandle(ref Rec rec, AuditLogonEnv env, string logonId, string username, string userSid, string handleId, string processId, string processName, string objectName, string accessMask, ref int sentItems)
        {
            var access = (uint)GetPid(accessMask);

            AuditHandle handle;
            if (!env.Handles.TryGetValue(handleId, out handle))
            {
                handle = new AuditHandle()
                    {
                        Handle = handleId,
                        Object = new AuditObject()
                    };
                env.Handles[handleId] = handle;
            }

            if (!string.IsNullOrEmpty(objectName))
            {
                var kernel = RegKernelPath.Match(objectName);
                if (kernel.Success)
                    objectName = QueryDosPath(kernel.Groups[1].Value, kernel.Groups[2].Value);
            }
            handle.Object.LogonId = logonId;
            handle.Object.Name = objectName;
            handle.Object.Owner = user;
            handle.Object.OwnerSid = userSid;
            handle.OwnerProcess[processId] = processName;
            handle.Object.Handles[handleId] = handle;
            handle.AccessType = (AccessMask)access;
            try
            {
                AuditHandle lastHandle;
                if (env.ProcessLastAudit.TryGetValue(processId, out lastHandle))
                {
                    if (lastHandle.Object.Name == handle.Object.Name)
                    {
                        lastHandle.AccessType |= handle.AccessType;
                        env.Handles.Remove(handle.Handle);
                        handle = lastHandle;
                        return;
                    }
                    if ((lastHandle.AccessType & AccessMask.Delete) == AccessMask.Delete
                        && (handle.AccessType & (AccessMask.WriteOrAddFile | AccessMask.AppendOrAddSubDir)) != AccessMask.None)
                    {
                        string customStr2;
                        if ((handle.AccessType & AccessMask.WriteOrAddFile) == AccessMask.WriteOrAddFile)
                            customStr2 = "File";
                        else
                            customStr2 = "Directory";
                        env.Handles.Remove(lastHandle.Handle);
                        int pid = GetPid(processId);
                        var prevName = lastHandle.Object.Name;
                        var op = "MOVE";
                        if (prevName != null)
                        {
                            var currName = handle.Object.Name;
                            if (currName != null)
                            {
                                if (!currName.EndsWith("\\"))
                                    currName += "\\";
                                if (currName.Length < prevName.Length &&
                                    prevName.StartsWith(currName) &&
                                    prevName.IndexOf('\\', currName.Length) < 0)
                                    op = "RENAME";
                            }
                        }
                        SendData(ref rec, op, customStr2, lastHandle.Object.Name, userSid, username, processName,
                                 pid, accessMask, objectName);
                        sentItems++;
                    }
                }
                else if ((handle.AccessType & AccessMask.WriteDac) == AccessMask.WriteDac)
                {
                    int pid = GetPid(processId);
                    if ((handle.AccessType & FileMask) == FileMask)
                    {
                        SendData(ref rec, "NEW", "File", handle.Object.Name, userSid, user, processName, pid, accessMask,
                                 string.Empty);
                        sentItems++;
                    }
                    else if ((handle.AccessType & DirectoryMask) == DirectoryMask)
                    {
                        SendData(ref rec, "NEW", "Directory", handle.Object.Name, userSid, user, processName, pid,
                                 accessMask, string.Empty);
                        sentItems++;
                    }
                }
            }
            finally
            {
                env.ProcessLastAudit[processId] = handle;
            }
        }
        private void AuditDeleteHandle(ref Rec rec, AuditLogonEnv env, string user, string userSid,
                                          string handleId, string processId, string processName, ref int sentItems)
        {
            var pid = GetPid(processId);

            AuditHandle handle;
            if (env.Handles.TryGetValue(handleId, out handle))
            {
                if ((handle.AccessType & AccessMask.Delete) == AccessMask.Delete)
                {
                    env.Handles.Remove(handleId);
                    SendData(ref rec, "DELETED", "File", handle.Object.Name, userSid, user, processName, pid, string.Format("{0:X}", handle.AccessType), string.Empty);
                    sentItems++;
                }
            }
        }
        private void AuditDuplicateHandle(ref Rec rec, AuditLogonEnv env, string logonId, string user, string userSid, string sourceHandleId, string sourceProcessId, string targetHandleId, string targetProcessId, ref int sentItems)
        {
            try
            {
                long pid = GetPid(targetProcessId);
                if (pid == 4)
                    targetProcessId = sourceProcessId;

                AuditCloseHandle(ref rec, env, user, userSid, targetHandleId, targetProcessId, string.Empty, ref sentItems, false);

                AuditHandle handle;
                if (!env.Handles.TryGetValue(sourceHandleId, out handle))
                {
                    handle = new AuditHandle()
                        {
                            Handle = sourceHandleId,
                            Object = new AuditObject() { LogonId = logonId, Owner = user, OwnerSid = userSid }
                        };
                    env.Handles[sourceHandleId] = handle;
                }
                env.Handles[targetHandleId] = handle;
                handle.Object.Handles[sourceHandleId] = handle;
                handle.Object.Handles[targetHandleId] = handle;
                handle.OwnerProcess[sourceProcessId] = sourceProcessId;
                if (targetProcessId != sourceProcessId)
                    handle.OwnerProcess[targetProcessId] = targetProcessId;
            }
            finally
            {
                env.ProcessLastAudit.Remove(sourceProcessId);
            }
        }
 private void AuditCloseHandle(ref Rec rec, AuditLogonEnv env, string username, string userSid, string handleId, string processId, string processName, ref int sentItems, bool removeProcessLast = true)
 {
     try
     {
         AuditHandle handle;
         if (env.Handles.TryGetValue(handleId, out handle))
         {
             if ((handle.AccessType & BeforeMoveMask) == BeforeMoveMask)
                 return;
             handle.OwnerProcess.Remove(processId);
             if (handle.OwnerProcess.Keys.Count == 0)
             {
                 if (handle.AccessType == AccessMask.Delete)
                 {
                     SendData(ref rec, "DELETED", "File", handle.Object.Name, userSid, username, processName, GetPid(processId), string.Format("{0:X}", handle.AccessType), string.Empty);
                     sentItems++;
                 }
                 env.Handles.Remove(handleId);
                 handle.Object.Handles.Remove(handleId);
             }
         }
     }
     finally
     {
         if (removeProcessLast)
             env.ProcessLastAudit.Remove(processId);
     }
 }