private void WriteToSecurityLog(int auditId, bool success, params object[] parameters) { ThrowIfDisposed(); // // Report the event // IntPtr paramArray = IntPtr.Zero; GCHandle[] handleArray = null; try { if (parameters.Length > 0) { handleArray = new GCHandle[parameters.Length + 1]; int j = 0; handleArray[j] = GCHandle.Alloc(new byte[Marshal.SizeOf(typeof(Win32Native.AUDIT_PARAM)) * parameters.Length], GCHandleType.Pinned); paramArray = handleArray[j].AddrOfPinnedObject(); j++; for (int i = 0; i < parameters.Length; i++) { Win32Native.AUDIT_PARAM paramArrayElement = new Win32Native.AUDIT_PARAM(); paramArrayElement.Flags = 0; paramArrayElement.Length = 0; System.Type type = parameters[i].GetType(); if (type == typeof(String)) { paramArrayElement.Type = (uint)AUDIT_PARAM_TYPE.APT_String; handleArray[j] = GCHandle.Alloc((parameters[i] as string), GCHandleType.Pinned); paramArrayElement.Data0 = handleArray[j].AddrOfPinnedObject(); paramArrayElement.Data1 = IntPtr.Zero; j++; } else if (type == typeof(uint) || type == typeof(ushort) || type == typeof(byte) || type == typeof(int) || type == typeof(short) || type == typeof(sbyte)) { paramArrayElement.Type = (uint)AUDIT_PARAM_TYPE.APT_Ulong; paramArrayElement.Data0 = new IntPtr((int)parameters[i]); paramArrayElement.Data1 = IntPtr.Zero; } /* * else if ( type == typeof( SecurityIdentifier )) * { * SecurityIdentifier sid = parameters[i] as SecurityIdentifier; * byte[] binaryForm = new byte[sid.BinaryLength]; * sid.GetBinaryForm( binaryForm, 0 ); * * paramArrayElement.Type = ( uint )AUDIT_PARAM_TYPE.APT_Sid; * // Can use BinaryForm property if inside of BCL * handleArray[j] = GCHandle.Alloc( binaryForm, GCHandleType.Pinned ); * paramArrayElement.Data0 = handleArray[j].AddrOfPinnedObject(); * paramArrayElement.Data1 = IntPtr.Zero; * j++; * } */ else if (type == typeof(Guid)) { paramArrayElement.Type = (uint)AUDIT_PARAM_TYPE.APT_Guid; handleArray[j] = GCHandle.Alloc(((Guid)parameters[i]).ToByteArray(), GCHandleType.Pinned); paramArrayElement.Data0 = handleArray[j].AddrOfPinnedObject(); paramArrayElement.Data1 = IntPtr.Zero; j++; } else if (type == typeof(DateTime)) { paramArrayElement.Type = (uint)AUDIT_PARAM_TYPE.APT_Time; paramArrayElement.Data0 = new IntPtr((int)(((DateTime)parameters[i]).ToFileTime() & 0xFFFFFFFF)); paramArrayElement.Data1 = new IntPtr((int)((((DateTime)parameters[i]).ToFileTime() >> 32) & 0xFFFFFFFF)); } // Add LogonId and Luid support, if necessary else if (type == typeof(Int64) || type == typeof(UInt64)) { paramArrayElement.Type = (uint)AUDIT_PARAM_TYPE.APT_Int64; paramArrayElement.Data0 = new IntPtr((int)((uint)parameters[i]) & 0xFFFFFFFF); paramArrayElement.Data1 = new IntPtr((int)(((int)parameters[i] >> 32) & 0xFFFFFFFF)); } else { throw new ArgumentException("Type unsuitable for auditing", nameof(parameters)); } // // Marshal the structure into the parameters array // Marshal.StructureToPtr(paramArrayElement, new IntPtr(paramArray.ToInt64() + i * Marshal.SizeOf(typeof(Win32Native.AUDIT_PARAM))), false); } } Win32Native.AUDIT_PARAMS auditParams = new Win32Native.AUDIT_PARAMS(); auditParams.Length = 0; auditParams.Flags = success ? Win32Native.APF_AuditSuccess : Win32Native.APF_AuditFailure; unchecked { auditParams.Count = (ushort)parameters.Length; } auditParams.Parameters = paramArray; if (false == Win32Native.AuthzReportSecurityEventFromParams(0, this.securityLogHandle, (uint)auditId, null, auditParams)) { int error = Marshal.GetLastWin32Error(); if (error == Win32Native.ERROR_NOT_ENOUGH_MEMORY) { throw new OutOfMemoryException(); } else if (error == Win32Native.ERROR_ACCESS_DENIED) { throw new UnauthorizedAccessException(); } else if (error == Win32Native.ERROR_INVALID_PARAMETER) { // Marshaling failed! throw new Win32Exception(error); } else { throw new Win32Exception(error); } } } finally { if (handleArray != null) { for (int i = 0; i < handleArray.Length; i++) { if (handleArray[i].IsAllocated) { handleArray[i].Free(); } } } } }