public static DeltaEventEntry TryCreate(IntPtr contactHandle, DBEVENTINFO dbEventInfo, byte[] eventBlob) { try { return new DeltaEventEntry(contactHandle, dbEventInfo, eventBlob); } catch { return null; } }
private unsafe void GatherNewEvents(LinkedList<DeltaEntry> entries) { MirandaContext context = MirandaContext.Current; foreach (KeyValuePair<IntPtr, IntPtr> contactEventPair in DatabaseSnapshot.EventHandles) { UIntPtr wEventHandle = Translate.ToHandle(contactEventPair.Value); InteropBuffer buffer = InteropBufferPool.AcquireBuffer(); try { while (AdvanceToNextEvent(ref wEventHandle, contactEventPair.Key)) { int blobSize = context.CallService(MS_DB_EVENT_GETBLOBSIZE, wEventHandle, IntPtr.Zero); if (blobSize == -1) continue; PrepareBlobBuffer(ref buffer, blobSize); DBEVENTINFO dbEventInfo = new DBEVENTINFO(blobSize, buffer.IntPtr); if (context.CallService(MS_DB_EVENT_GET, wEventHandle, new IntPtr(&dbEventInfo)) != 0) continue; byte[] blob = new byte[blobSize]; Marshal.Copy(buffer.IntPtr, blob, 0, blob.Length); DeltaEventEntry entry = DeltaEventEntry.TryCreate(contactEventPair.Key, dbEventInfo, blob); if (entry == null) continue; entries.AddLast(entry); } } finally { if (buffer.Locked) buffer.Unlock(); InteropBufferPool.ReleaseBuffer(buffer); } } }
private unsafe void SimulateNewEvent() { DBEVENTINFO info = new DBEVENTINFO(0, IntPtr.Zero); info.Module = Translate.ToHandle("ICQ", StringEncoding.Ansi).IntPtr; UnmanagedStringHandle str = new UnmanagedStringHandle("aěščřšžšž", StringEncoding.MirandaDefault); info.BlobSize = (uint)str.Size; info.BlobPtr = str; info.EventType = 0; info.Flags = 0; info.Timestamp = Utilities.GetTimestamp(); IntPtr result = new IntPtr(MirandaContext.Current.CallService("DB/Event/Add", Translate.ToHandle(MirandaContext.Current.MirandaDatabase.FindContact("177147220", ContactInfoProperty.UniqueID, StringEncoding.Ansi).MirandaHandle), new UnmanagedStructHandle<DBEVENTINFO>(ref info))); }
public IntPtr AddEvent(ContactInfo associatedContact, object data, string owner, DatabaseEventType type, DatabaseEventProperties flags, DateTime? timestamp, bool throwOnFailure) { if (associatedContact == null) throw new ArgumentNullException("associatedContact"); if (String.IsNullOrEmpty(owner)) throw new ArgumentNullException("owner"); if (data == null) throw new ArgumentNullException("data"); IntPtr pBlob = IntPtr.Zero; UnmanagedStructHandle<DBEVENTINFO> nativeStruct = UnmanagedStructHandle<DBEVENTINFO>.Empty; try { int totalBytes; if (data is string) { totalBytes = DBEVENTINFO.LayoutAnsiUniString((string)data, out pBlob); } else if (data is byte[]) { byte[] dataBytes = (byte[])data; totalBytes = dataBytes.Length; pBlob = Marshal.AllocHGlobal(totalBytes); Marshal.Copy(dataBytes, 0, pBlob, dataBytes.Length); } else throw new ArgumentOutOfRangeException("data"); DBEVENTINFO info = new DBEVENTINFO(0, IntPtr.Zero); info.Module = Translate.ToHandle(owner, StringEncoding.Ansi).IntPtr; info.BlobSize = (uint)totalBytes; info.BlobPtr = pBlob; info.EventType = (ushort)type; info.Flags = (uint)flags; info.Timestamp = Utilities.GetTimestamp(timestamp.HasValue ? timestamp.Value : DateTime.Now); nativeStruct = new UnmanagedStructHandle<DBEVENTINFO>(ref info, pBlob, info.Module); IntPtr eventHandle = (IntPtr)MirandaContext.Current.CallService(MS_DB_EVENT_ADD, associatedContact.MirandaHandle, nativeStruct.IntPtr); if (eventHandle == IntPtr.Zero && throwOnFailure) throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_DB_EVENT_ADD, eventHandle.ToString())); else return eventHandle; } finally { nativeStruct.Free(); } }
/// <summary> /// Gets the event data. /// </summary> /// <param name="dbEventInfo">[REF] <see cref="DBEVENTINFO"/> struct.</param> /// <returns>Event data.</returns> private unsafe static string GetEventData(ref DBEVENTINFO dbEventInfo) { string data; DBEVENTGETTEXT dbGetText = new DBEVENTGETTEXT(); dbGetText.Codepage = 0; dbGetText.DataType = (int)DatabaseSettingType.UnicodeString; IntPtr pText; fixed (void* pDbEventInfo = &dbEventInfo) { dbGetText.DbEventInfoPtr = new IntPtr(pDbEventInfo); pText = (IntPtr)MirandaContext.Current.CallServiceUnsafe(MS_DB_EVENT_GETTEXT, null, &dbGetText); } if (pText != IntPtr.Zero) { data = Translate.ToString(pText, StringEncoding.Unicode); MirandaContext.Current.MirandaMemoryManager.Free(pText); } else throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_DB_EVENT_GETTEXT, "null")); return data; }
/// <summary> /// Gets the event module. /// </summary> /// <param name="dbEventInfo">[REF] <see cref=">DBEVENTINFO"/> struct.</param> /// <returns>Event module.</returns> private static Protocol GetEventModule(ref DBEVENTINFO dbEventInfo) { Protocol owningModule; bool moduleFound = false; if (dbEventInfo.Module != IntPtr.Zero) moduleFound = MirandaContext.Current.Protocols.TryGetValue(Translate.ToString(dbEventInfo.Module, StringEncoding.Ansi), out owningModule); else owningModule = Protocol.UnknownProtocol; if (!moduleFound) owningModule = Protocol.UnknownProtocol; return owningModule; }
/// <summary> /// Gets the event timestamp. /// </summary> /// <param name="dbEventInfo">[REF] <see cref="DBEVENTINFO"/> struct.</param> /// <param name="blobBuffer">Buffer to reuse.</param> /// <param name="timestamp">[OUT] Timestamp.</param> private static void GetEventTimestamp(ref DBEVENTINFO dbEventInfo, InteropBuffer blobBuffer, out DateTime timestamp) { try { DBTIMETOSTRING timeToString = new DBTIMETOSTRING("s D"); timeToString.MaxBytes = blobBuffer.Size; timeToString.Output = blobBuffer.IntPtr; unsafe { MirandaContext.Current.CallServiceUnsafe(MS_DB_TIME_TIMESTAMPTOSTRING, (void*)dbEventInfo.Timestamp, &timeToString); } timestamp = DateTime.Parse(Translate.ToString(timeToString.Output, StringEncoding.Ansi)); } catch (FormatException) { timestamp = DateTime.MinValue; } }
/// <summary> /// Populates the blob buffer set by the <see cref="DBEVENTINFO"/> parameter. /// </summary> /// <param name="dbEventInfo">[REF] <see cref="DBEVENTINFO"/> struct identifiing the buffer.</param> /// <param name="eventHandle">Event handle.</param> /// <exception cref="MirandaException">Buffer could bet populated.</exception> private unsafe static void PopulateBlobBuffer(ref DBEVENTINFO dbEventInfo, IntPtr eventHandle) { int result; fixed (void* pDbEventInfo = &dbEventInfo) result = MirandaContext.Current.CallServiceUnsafe(MS_DB_EVENT_GET, eventHandle.ToPointer(), pDbEventInfo); if (result != 0) throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_DB_EVENT_GET, result.ToString())); }
/// <summary> /// Get the event information from a <see cref="DBEVENTINFO"/> struct. /// </summary> /// <param name="dbEventInfo">[REF] <see cref="DBEVENTINFO"/> struct.</param> /// <param name="mirandaHandle">Event handle (the blob buffer will be populated if not null).</param> /// <param name="blobBuffer">Buffer to use for blob marshaling.</param> /// <param name="type">[OUT] Event type.</param> /// <param name="flags">[OUT] Event flags.</param> /// <param name="data">[OUT] Event data.</param> /// <param name="owningModule">[OUT] Event related module.</param> /// <param name="timestamp">[OUT] Event timestamp.</param> private static void GetEventInfo(ref DBEVENTINFO dbEventInfo, IntPtr eventHandle, InteropBuffer blobBuffer, out DatabaseEventType type, out DatabaseEventProperties flags, out string data, out Protocol owningModule, out DateTime timestamp) { MirandaContext context = MirandaContext.Current; unsafe { // If the event handle is set, we probably want to populate the blob buffer... if (eventHandle != IntPtr.Zero) PopulateBlobBuffer(ref dbEventInfo, eventHandle); type = (DatabaseEventType)dbEventInfo.EventType; flags = (DatabaseEventProperties)dbEventInfo.Flags; data = GetEventData(ref dbEventInfo); } owningModule = GetEventModule(ref dbEventInfo); GetEventTimestamp(ref dbEventInfo, blobBuffer, out timestamp); }
/// <summary> /// Prepares the <see cref="DBEVENTINFO"/> for information extraction and the blob buffer. /// </summary> /// <param name="eventHandle">Event handle.</param> /// <param name="dbEventInfo">[OUT] DB event info to marshal data into.</param> /// <param name="buffer">[OUT] Locked Blob buffer.</param> private unsafe static void PrepareDbEventInfo(IntPtr eventHandle, out DBEVENTINFO dbEventInfo, out InteropBuffer buffer) { int blobSize = MirandaContext.Current.CallServiceUnsafe(MS_DB_EVENT_GETBLOBSIZE, eventHandle.ToPointer(), null); if (blobSize == -1) throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_DB_EVENT_GETBLOBSIZE, blobSize.ToString())); // Acquire a buffer for the blob buffer = InteropBufferPool.AcquireBuffer(blobSize); buffer.Lock(); dbEventInfo = new DBEVENTINFO(blobSize, buffer.IntPtr); }
private DeltaEventEntry(IntPtr contactHandle, DBEVENTINFO dbEventInfo, byte[] eventBlob) : base(contactHandle) { EventInfo = dbEventInfo; EventBlob = eventBlob; EventModule = Translate.ToString(dbEventInfo.Module, StringEncoding.Ansi); }