mit hyphen
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
internal class CallbackWrapper
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private string serviceName;
|
||||
public string ServiceName
|
||||
{
|
||||
get { return serviceName; }
|
||||
protected set { serviceName = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
private CallbackWrapper(string serviceName)
|
||||
{
|
||||
if (String.IsNullOrEmpty(serviceName))
|
||||
throw new ArgumentNullException("serviceName");
|
||||
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
public static Callback Create(string serviceName)
|
||||
{
|
||||
return new Callback(new CallbackWrapper(serviceName).Callback);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected int Callback(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return MirandaContext.Current.CallService(ServiceName, wParam, lParam);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[Serializable]
|
||||
public class ConfigurationException : Exception
|
||||
{
|
||||
public ConfigurationException() { }
|
||||
public ConfigurationException(string message) : base(message) { }
|
||||
public ConfigurationException(string message, Exception inner) : base(message, inner) { }
|
||||
protected ConfigurationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Configuration;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class ConfigurationOptionsAttribute : Attribute
|
||||
{
|
||||
#region .ctors
|
||||
|
||||
internal ConfigurationOptionsAttribute() { }
|
||||
|
||||
public ConfigurationOptionsAttribute(string configurationVersion) : this(configurationVersion, false, true) { }
|
||||
|
||||
[Obsolete("Will be removed in future. Use named arguments instead.", true)]
|
||||
public ConfigurationOptionsAttribute(bool encrypt, bool profileBound) : this(null, encrypt, profileBound) { }
|
||||
|
||||
[Obsolete("Will be removed in future. Use named arguments instead.", false)]
|
||||
public ConfigurationOptionsAttribute(string configurationVersion, bool encrypt, bool profileBound)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(configurationVersion))
|
||||
this.version = new Version(configurationVersion);
|
||||
|
||||
this.encrypt = encrypt;
|
||||
this.profileBound = profileBound;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private readonly Version version;
|
||||
public Version Version
|
||||
{
|
||||
get { return version; }
|
||||
}
|
||||
|
||||
private bool profileBound;
|
||||
public bool ProfileBound
|
||||
{
|
||||
get { return profileBound; }
|
||||
set { profileBound = value; }
|
||||
}
|
||||
|
||||
private bool encrypt;
|
||||
public bool Encrypt
|
||||
{
|
||||
get { return encrypt; }
|
||||
set { encrypt = value; }
|
||||
}
|
||||
|
||||
private Type storage;
|
||||
public Type Storage
|
||||
{
|
||||
get { return storage; }
|
||||
set { storage = value; }
|
||||
}
|
||||
|
||||
private Type encryption;
|
||||
public Type Encryption
|
||||
{
|
||||
get { return encryption; }
|
||||
set { encryption = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
internal ConfigurationOptionsAttribute Finalize()
|
||||
{
|
||||
if (storage == null)
|
||||
storage = typeof(IsolatedStorage);
|
||||
|
||||
if (encrypt && encryption == null)
|
||||
encryption = typeof(WindowsEncryption);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,753 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using Virtuoso.Hyphen;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[Serializable]
|
||||
public class ContactInfo : MirandaItem, ISerializable
|
||||
{
|
||||
#region Enums
|
||||
|
||||
[Flags]
|
||||
private enum ContactDisplayNameOptions : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Will return char*, as usual.
|
||||
/// </summary>
|
||||
Ansi = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Will never return the user's custom name.
|
||||
/// </summary>
|
||||
NoMyHandle = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Will return TCHAR* instead of char*.
|
||||
/// </summary>
|
||||
Unicode = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Will not use the cache.
|
||||
/// </summary>
|
||||
NoCache = 4
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Contants
|
||||
|
||||
private const string MS_DB_CONTACT_IS = "DB/Contact/Is",
|
||||
MS_PROTO_GETCONTACTBASEPROTO = "Proto/GetContactBaseProto",
|
||||
MS_DB_CONTACT_WRITESETTING = "DB/Contact/WriteSetting",
|
||||
MS_DB_CONTACT_GETSETTING = "DB/Contact/GetSetting",
|
||||
MS_DB_CONTACT_GETSETTINGSTATIC = "DB/Contact/GetSettingStatic",
|
||||
MS_DB_CONTACT_DELETESETTING = "DB/Contact/DeleteSetting",
|
||||
|
||||
MS_DB_CONTACT_ADD = "DB/Contact/Add",
|
||||
MS_DB_CONTACT_DELETE = "DB/Contact/Delete",
|
||||
|
||||
MS_CLIST_GETCONTACTDISPLAYNAME = "CList/GetContactDisplayName",
|
||||
|
||||
SETTING_STATUS = "Status",
|
||||
|
||||
MS_MSG_SENDMESSAGE = "SRMsg/SendCommand",
|
||||
MS_MSG_SENDMESSAGE_2 = "SRMsg/LaunchMessageWindow";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
private static readonly object SyncObject = new object();
|
||||
private static readonly ContactInfo meNeutral = new ContactInfo();
|
||||
|
||||
private readonly Protocol owningModule;
|
||||
|
||||
private object value;
|
||||
private ContactInfoPropertyType valueType;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
private ContactInfo()
|
||||
: base(IntPtr.Zero, ItemType.Contact)
|
||||
{
|
||||
this.owningModule = Protocol.UnknownProtocol;
|
||||
}
|
||||
|
||||
protected ContactInfo(SerializationInfo info, StreamingContext context)
|
||||
: this((IntPtr)info.GetInt64("MirandaHandle"))
|
||||
{
|
||||
}
|
||||
|
||||
[CLSCompliant(false), Obsolete("Will be removed in the future, use FromHandle(UIntPtr) instead.")]
|
||||
public ContactInfo(UIntPtr contactHandle) : this(Translate.ToHandle(contactHandle)) { }
|
||||
|
||||
[Obsolete("Will be removed in the future, use FromHandle(IntPtr) instead.")]
|
||||
public ContactInfo(IntPtr contactHandle)
|
||||
: base(contactHandle, ItemType.Contact)
|
||||
{
|
||||
MirandaContext context = MirandaContext.Current;
|
||||
|
||||
if (contactHandle != IntPtr.Zero && context.CallService(MS_DB_CONTACT_IS, contactHandle, IntPtr.Zero) == 0)
|
||||
throw new ArgumentException("Contact not found in Miranda database.");
|
||||
|
||||
IntPtr protoNamePtr = GetModuleNamePtr(contactHandle);
|
||||
|
||||
if (protoNamePtr != IntPtr.Zero)
|
||||
{
|
||||
string protoName = Translate.ToString(protoNamePtr, StringEncoding.Ansi);
|
||||
MirandaContext.Current.Protocols.TryGetValue(protoName, out owningModule);
|
||||
}
|
||||
|
||||
if (owningModule == null)
|
||||
{
|
||||
owningModule = Protocol.UnknownProtocol;
|
||||
|
||||
if (contactHandle != IntPtr.Zero)
|
||||
Log.DebuggerWrite(5, Loader.LogCategory, "Unable to obtain contact's protocol");
|
||||
}
|
||||
|
||||
this.MirandaHandle = contactHandle;
|
||||
}
|
||||
|
||||
public static ContactInfo FromHandle(IntPtr contactHandle)
|
||||
{
|
||||
return new ContactInfo(contactHandle);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static ContactInfo FromHandle(UIntPtr contactHandle)
|
||||
{
|
||||
return new ContactInfo(contactHandle);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public ContactInfoPropertyType PropertyType
|
||||
{
|
||||
get { return valueType; }
|
||||
}
|
||||
|
||||
public object PropertyValue
|
||||
{
|
||||
get { return this.value; }
|
||||
}
|
||||
|
||||
public Protocol OwningModule
|
||||
{
|
||||
get { return owningModule; }
|
||||
}
|
||||
|
||||
public bool IsSelf
|
||||
{
|
||||
get
|
||||
{
|
||||
return (MirandaHandle == IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
public static ContactInfo MeNeutral
|
||||
{
|
||||
get
|
||||
{
|
||||
return meNeutral;
|
||||
}
|
||||
}
|
||||
|
||||
public StatusMode? Status
|
||||
{
|
||||
get
|
||||
{
|
||||
if (String.IsNullOrEmpty(OwningModule.Name))
|
||||
return null;
|
||||
|
||||
object obj = ReadSetting(SETTING_STATUS, DatabaseSettingType.UInt16);
|
||||
|
||||
if (obj != null)
|
||||
return (StatusMode)(UInt16)obj; //(StatusMode)Enum.Parse(typeof(StatusMode), (Int16) obj);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetDisplayName(MirandaHandle);
|
||||
}
|
||||
}
|
||||
|
||||
private object uniqueID;
|
||||
public object UniqueID
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SyncObject)
|
||||
{
|
||||
if (uniqueID == null)
|
||||
{
|
||||
ContactInfoPropertyType type;
|
||||
GetUniqueID(MirandaHandle, out uniqueID, out type);
|
||||
}
|
||||
|
||||
return uniqueID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
#region Settings/Write
|
||||
|
||||
public bool WriteSetting(string name, object value, DatabaseSettingType saveAs)
|
||||
{
|
||||
return WriteSetting(name, OwningModule, value, saveAs);
|
||||
}
|
||||
|
||||
public bool WriteSetting(string name, ISettingOwner owner, object value, DatabaseSettingType saveAs)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
return WriteSetting(name, owner.Name, value, saveAs);
|
||||
}
|
||||
|
||||
public bool WriteSettingAsBlob(string name, ISettingOwner owner, byte[] blob)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
return WriteSettingAsBlob(name, owner.Name, blob);
|
||||
}
|
||||
|
||||
public bool WriteSettingAsBlob(string name, string owner, byte[] blob)
|
||||
{
|
||||
if (blob == null)
|
||||
throw new ArgumentNullException("blob");
|
||||
|
||||
throw new NotImplementedException();
|
||||
|
||||
//return WriteSetting(name, owner, blob, DatabaseSettingType.Blob);
|
||||
}
|
||||
|
||||
public unsafe bool WriteSetting(string name, string owner, object value, DatabaseSettingType saveAs)
|
||||
{
|
||||
if (String.IsNullOrEmpty(owner))
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (String.IsNullOrEmpty(name))
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
UnmanagedStringHandle valueHandle = UnmanagedStringHandle.Empty;
|
||||
UnmanagedStringHandle nameHandle = Translate.ToHandle(name, StringEncoding.Ansi);
|
||||
UnmanagedStringHandle moduleNameHandle = Translate.ToHandle(owner, StringEncoding.Ansi);
|
||||
|
||||
IntPtr blobPtr = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
DBCONTACTWRITESETTING dbSetting = new DBCONTACTWRITESETTING();
|
||||
dbSetting.Name = nameHandle;
|
||||
dbSetting.Module = moduleNameHandle;
|
||||
dbSetting.Value = new DBVARIANT();
|
||||
dbSetting.Value.Type = (byte)saveAs;
|
||||
|
||||
switch (saveAs)
|
||||
{
|
||||
case DatabaseSettingType.AsciiString:
|
||||
valueHandle = new UnmanagedStringHandle(value.ToString(), StringEncoding.Ansi);
|
||||
dbSetting.Value.Text.TextPtr = valueHandle.IntPtr;
|
||||
break;
|
||||
case DatabaseSettingType.UnicodeString:
|
||||
case DatabaseSettingType.UTF8String:
|
||||
valueHandle = new UnmanagedStringHandle(value.ToString(), StringEncoding.Unicode);
|
||||
dbSetting.Value.Text.TextPtr = valueHandle.IntPtr;
|
||||
break;
|
||||
|
||||
case DatabaseSettingType.Byte:
|
||||
dbSetting.Value.Primitives.Byte = Convert.ToByte(value);
|
||||
break;
|
||||
case DatabaseSettingType.UInt16:
|
||||
dbSetting.Value.Primitives.Word = Convert.ToUInt16(value);
|
||||
break;
|
||||
case DatabaseSettingType.UInt32:
|
||||
dbSetting.Value.Primitives.DWord = Convert.ToUInt32(value);
|
||||
break;
|
||||
case DatabaseSettingType.Blob:
|
||||
throw new NotImplementedException();
|
||||
|
||||
/*byte[] blob = value as byte[];
|
||||
|
||||
if (blob == null)
|
||||
throw new ArgumentException("value");
|
||||
|
||||
blobPtr = Marshal.AllocHGlobal(blob.Length);
|
||||
Marshal.Copy(blob, 0, blobPtr, blob.Length);
|
||||
|
||||
dbSetting.Value.Blob.BlobPtr = blobPtr;
|
||||
dbSetting.Value.Blob.Size = (UInt16)blob.Length;
|
||||
break;*/
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("saveAs");
|
||||
}
|
||||
|
||||
bool result = MirandaContext.Current.CallServiceUnsafe(MS_DB_CONTACT_WRITESETTING, MirandaHandle.ToPointer(), &dbSetting) == 0;
|
||||
Debug.Assert(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (FormatException fE)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("value", fE);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new MirandaException(TextResources.ExceptionMsg_ErrorWhileCallingMirandaService, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
valueHandle.Free();
|
||||
nameHandle.Free();
|
||||
moduleNameHandle.Free();
|
||||
|
||||
if (blobPtr != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(blobPtr);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Settings/Read
|
||||
|
||||
public object ReadSetting(string name, DatabaseSettingType readAs)
|
||||
{
|
||||
return ReadSetting(MirandaHandle, name, readAs);
|
||||
}
|
||||
|
||||
public static object ReadSetting(IntPtr contactHandle, string name, DatabaseSettingType readAs)
|
||||
{
|
||||
IntPtr pOwnerName = GetModuleNamePtr(contactHandle);
|
||||
|
||||
if (pOwnerName == IntPtr.Zero)
|
||||
throw new InvalidOperationException(TextResources.ExceptionMsg_OwnerUnknown);
|
||||
|
||||
return ReadSetting(contactHandle, name, Marshal.PtrToStringAnsi(pOwnerName), readAs);
|
||||
}
|
||||
|
||||
public object ReadSetting(string name, ISettingOwner owner, DatabaseSettingType readAs)
|
||||
{
|
||||
return ReadSetting(MirandaHandle, name, owner, readAs);
|
||||
}
|
||||
|
||||
public static object ReadSetting(IntPtr contactHandle, string name, ISettingOwner owner, DatabaseSettingType readAs)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
return ReadSetting(contactHandle, name, owner.Name, readAs);
|
||||
}
|
||||
|
||||
public object ReadSetting(string name, string owner, DatabaseSettingType readAs)
|
||||
{
|
||||
return ReadSetting(MirandaHandle, name, owner, readAs);
|
||||
}
|
||||
|
||||
public static object ReadSetting(IntPtr contactHandle, string name, string owner, DatabaseSettingType readAs)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name))
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
InteropBuffer buffer = InteropBufferPool.AcquireBuffer();
|
||||
|
||||
try
|
||||
{
|
||||
DBCONTACTGETSETTING dbSetting = new DBCONTACTGETSETTING();
|
||||
dbSetting.Name = name;
|
||||
|
||||
DBVARIANT dbVariant = new DBVARIANT();
|
||||
dbVariant.Type = (byte)readAs;
|
||||
|
||||
buffer.Lock();
|
||||
|
||||
if (readAs != DatabaseSettingType.Blob)
|
||||
{
|
||||
dbVariant.Text.TextPtr = buffer.IntPtr;
|
||||
dbVariant.Text.TextBufferSize = (ushort)buffer.Size;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//dbVariant.Blob.BlobPtr = buffer.IntPtr;
|
||||
}
|
||||
|
||||
return ReadSettingInternal(contactHandle, owner, ref dbSetting, ref dbVariant);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new MirandaException(TextResources.ExceptionMsg_ErrorWhileCallingMirandaService, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
buffer.Unlock();
|
||||
InteropBufferPool.ReleaseBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private static object ReadSettingInternal(IntPtr contactHandle, string owner, ref DBCONTACTGETSETTING setting, ref DBVARIANT variant)
|
||||
{
|
||||
UnmanagedStructHandle<DBCONTACTGETSETTING> dbSettingHandle = UnmanagedStructHandle<DBCONTACTGETSETTING>.Empty;
|
||||
UnmanagedStructHandle<DBVARIANT> dbVariantHandle = UnmanagedStructHandle<DBVARIANT>.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
dbVariantHandle = new UnmanagedStructHandle<DBVARIANT>(ref variant);
|
||||
|
||||
setting.Module = owner;
|
||||
setting.DbVariantPtr = dbVariantHandle.IntPtr;
|
||||
|
||||
dbSettingHandle = new UnmanagedStructHandle<DBCONTACTGETSETTING>(ref setting);
|
||||
|
||||
int result = MirandaContext.Current.CallService(MS_DB_CONTACT_GETSETTINGSTATIC, contactHandle, dbSettingHandle.IntPtr);
|
||||
Debug.Assert(result != 2, "Deleted setting encountered");
|
||||
|
||||
if (result != 0)
|
||||
return null;
|
||||
|
||||
dbVariantHandle.MarshalBack(out variant);
|
||||
return Translate.ValueFromVariant(ref variant);
|
||||
}
|
||||
finally
|
||||
{
|
||||
dbVariantHandle.Free();
|
||||
dbSettingHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Settings/Delete
|
||||
|
||||
public bool DeleteSetting(string name, ISettingOwner owner)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
return DeleteSetting(name, owner.Name);
|
||||
}
|
||||
|
||||
public bool DeleteSetting(string name, string owner)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name))
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
if (String.IsNullOrEmpty(owner))
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
DBCONTACTGETSETTING dbGetSetting = new DBCONTACTGETSETTING();
|
||||
dbGetSetting.Name = name;
|
||||
dbGetSetting.Module = owner;
|
||||
|
||||
UnmanagedStructHandle<DBCONTACTGETSETTING> dbSettingHandle = new UnmanagedStructHandle<DBCONTACTGETSETTING>(ref dbGetSetting);
|
||||
|
||||
try
|
||||
{
|
||||
return MirandaContext.Current.CallService(MS_DB_CONTACT_DELETESETTING, MirandaHandle, dbSettingHandle.IntPtr) == 0;
|
||||
}
|
||||
finally
|
||||
{
|
||||
dbSettingHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Converters
|
||||
|
||||
public static TId[] GetUniqueIDs<TId>(params ContactInfo[] contacts)
|
||||
{
|
||||
if (contacts == null)
|
||||
throw new ArgumentNullException("contacts");
|
||||
|
||||
if (contacts.Length == 0)
|
||||
return new TId[0];
|
||||
|
||||
return Array.ConvertAll<ContactInfo, TId>(contacts, delegate(ContactInfo contact)
|
||||
{
|
||||
if (contact != null)
|
||||
return contact.UniqueIdAs<TId>();
|
||||
else
|
||||
return default(TId);
|
||||
});
|
||||
}
|
||||
|
||||
public static string[] GetDisplayNames(params string[] uuids)
|
||||
{
|
||||
if (uuids == null)
|
||||
throw new ArgumentNullException("uuids");
|
||||
|
||||
if (uuids.Length == 0)
|
||||
return new string[0];
|
||||
|
||||
return Array.ConvertAll<string, string>(uuids, delegate(string uuid)
|
||||
{
|
||||
if (uuid == null)
|
||||
return null;
|
||||
|
||||
ContactInfo contact = MirandaContext.Current.MirandaDatabase.FindContact(uuid);
|
||||
|
||||
if (contact != null)
|
||||
return contact.DisplayName;
|
||||
else
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
private static IntPtr GetModuleNamePtr(IntPtr contactHandle)
|
||||
{
|
||||
return (IntPtr)MirandaContext.Current.CallService(MS_PROTO_GETCONTACTBASEPROTO, contactHandle, IntPtr.Zero);
|
||||
}
|
||||
|
||||
public static string GetDisplayName(IntPtr contactHandle)
|
||||
{
|
||||
ContactDisplayNameOptions options = ContactDisplayNameOptions.Unicode;
|
||||
|
||||
IntPtr pName = (IntPtr)MirandaContext.Current.CallService(MS_CLIST_GETCONTACTDISPLAYNAME, contactHandle, (IntPtr)options);
|
||||
|
||||
if (pName == IntPtr.Zero)
|
||||
return null;
|
||||
else
|
||||
return Translate.ToString(pName, StringEncoding.Unicode);
|
||||
}
|
||||
|
||||
public static bool GetUniqueID(IntPtr contactHandle, out object uuid, out ContactInfoPropertyType uuidType)
|
||||
{
|
||||
return GetProperty(contactHandle, ContactInfoProperty.UniqueID, out uuid, out uuidType);
|
||||
}
|
||||
|
||||
public static bool GetProperty(IntPtr contactHandle, ContactInfoProperty property, out object value, out ContactInfoPropertyType valueType)
|
||||
{
|
||||
CONTACTINFO contactInfo = new CONTACTINFO(contactHandle, GetModuleNamePtr(contactHandle));
|
||||
contactInfo.Flag = (byte)((byte)property | (byte)ContactInfoPropertyFlags.Unicode);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int result = MirandaContext.Current.CallServiceUnsafe(MirandaServices.MS_CONTACT_GETCONTACTINFO, null, &contactInfo);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
value = null;
|
||||
valueType = ContactInfoPropertyType.Unknown;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (valueType = (ContactInfoPropertyType)contactInfo.Type)
|
||||
{
|
||||
case ContactInfoPropertyType.Byte:
|
||||
value = Convert.ToByte(contactInfo.Value.ToInt32());
|
||||
break;
|
||||
case ContactInfoPropertyType.String:
|
||||
value = Translate.ToString(contactInfo.Value, StringEncoding.Unicode);
|
||||
break;
|
||||
case ContactInfoPropertyType.UInt16:
|
||||
value = Convert.ToUInt16(contactInfo.Value.ToInt32());
|
||||
break;
|
||||
case ContactInfoPropertyType.UInt32:
|
||||
value = contactInfo.Value.ToInt32();
|
||||
break;
|
||||
default:
|
||||
value = null;
|
||||
valueType = ContactInfoPropertyType.Unknown;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ISerializable Members
|
||||
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
info.AddValue("MirandaHandle", MirandaHandle.ToInt64());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public TId UniqueIdAs<TId>()
|
||||
{
|
||||
object uuid = UniqueID;
|
||||
return uuid == null ? default(TId) : (TId)Convert.ChangeType(uuid, typeof(TId));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return !Protocol.UnknownProtocol.Equals(OwningModule) ?
|
||||
String.Format("{0} ({1})", DisplayName, OwningModule.Name) : DisplayName;
|
||||
}
|
||||
|
||||
public static bool operator ==(ContactInfo first, ContactInfo second)
|
||||
{
|
||||
if (object.ReferenceEquals(first, second))
|
||||
return true;
|
||||
else if (object.ReferenceEquals(first, null))
|
||||
return false;
|
||||
else
|
||||
return first.Equals(second);
|
||||
}
|
||||
|
||||
public static bool operator !=(ContactInfo first, ContactInfo second)
|
||||
{
|
||||
return !(first == second);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
ContactInfo other = obj as ContactInfo;
|
||||
|
||||
if (object.ReferenceEquals(other, null))
|
||||
return false;
|
||||
else
|
||||
return GetHashCode() == other.GetHashCode();
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return MirandaHandle.ToInt32();
|
||||
}
|
||||
|
||||
public static ContactInfo CreateContact()
|
||||
{
|
||||
IntPtr hContact = (IntPtr)MirandaContext.Current.CallService(MS_DB_CONTACT_ADD);
|
||||
|
||||
if (hContact == IntPtr.Zero)
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_DB_CONTACT_ADD, hContact.ToString()));
|
||||
|
||||
return ContactInfo.FromHandle(hContact);
|
||||
}
|
||||
|
||||
public bool Delete()
|
||||
{
|
||||
if (IsSelf)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
return (0 == MirandaContext.Current.CallService(MS_DB_CONTACT_DELETE, MirandaHandle, IntPtr.Zero));
|
||||
}
|
||||
|
||||
public bool GetProperty(ContactInfoProperty property, StringEncoding stringEncoding)
|
||||
{
|
||||
return GetProperty(MirandaHandle, property, out value, out valueType);
|
||||
}
|
||||
|
||||
public int CallContactService(string serviceName)
|
||||
{
|
||||
return CallContactService(serviceName, UIntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public int CallContactService(string serviceName, UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (serviceName == null)
|
||||
throw new ArgumentNullException("serviceName");
|
||||
|
||||
CCSDATA ccsData = new CCSDATA(this, serviceName);
|
||||
ccsData.WParam = wParam;
|
||||
ccsData.LParam = lParam;
|
||||
|
||||
try
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return MirandaContext.Current.CallServiceUnsafe(MirandaServices.MS_PROTO_CALLCONTACTSERVICE, null, &ccsData);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ccsData.Free();
|
||||
}
|
||||
}
|
||||
|
||||
public void SendMessage(string message)
|
||||
{
|
||||
if (message == null)
|
||||
throw new ArgumentNullException("message");
|
||||
|
||||
UnmanagedStringHandle nativeHandle = UnmanagedStringHandle.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
nativeHandle = new UnmanagedStringHandle(message, StringEncoding.Ansi);
|
||||
CallContactService(MirandaServices.PS_MESSAGE, UIntPtr.Zero, nativeHandle.IntPtr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
nativeHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenMessageWindow()
|
||||
{
|
||||
OpenMessageWindow(null);
|
||||
}
|
||||
|
||||
public void OpenMessageWindow(string message)
|
||||
{
|
||||
UnmanagedStringHandle messageHandle = UnmanagedStringHandle.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
if (!String.IsNullOrEmpty(message))
|
||||
messageHandle = new UnmanagedStringHandle(message, StringEncoding.Ansi);
|
||||
|
||||
int result = (int)CallbackResult.Success;
|
||||
|
||||
if (result != MirandaContext.Current.CallService(MS_MSG_SENDMESSAGE, MirandaHandle, messageHandle.IntPtr))
|
||||
if ((int)CallbackResult.Success != (result = MirandaContext.Current.CallService(MS_MSG_SENDMESSAGE_2, MirandaHandle, messageHandle.IntPtr)))
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_MSG_SENDMESSAGE, result.ToString()));
|
||||
}
|
||||
finally
|
||||
{
|
||||
messageHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public enum ContactInfoProperty : byte
|
||||
{
|
||||
// Types of information you can retreive by setting the dwFlag in CONTACTINFO
|
||||
FirstName = 1, // returns first eventName (string)
|
||||
LastName = 2, // returns last eventName (string)
|
||||
Nick = 3, // returns nick eventName (string)
|
||||
CustomNick = 4, // returns custom nick name, clist name (string)
|
||||
Email = 5, // returns email (string)
|
||||
City = 6, // returns city (string)
|
||||
State = 7, // returns state (string)
|
||||
Country = 8, // returns country (string)
|
||||
Phone = 9, // returns phone (string)
|
||||
HomePage = 10, // returns homepage (string)
|
||||
About = 11, // returns about info (string)
|
||||
Gender = 12, // returns gender (byte,'M','F' character)
|
||||
Age = 13, // returns age (byte, 0==unspecified)
|
||||
FirstAndLastName = 14, // returns first eventName + last eventName (string)
|
||||
UniqueID = 15, // returns uniqueid, protocol username (must check type for type of return)
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum ContactInfoPropertyFlags : byte
|
||||
{
|
||||
Unicode = 0x80,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,503 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Drawing;
|
||||
using Virtuoso.Hyphen.Mini;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public sealed class ContactList : EventPublisher
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string ME_CLC_SHOWINFOTIP = "CLC/ShowInfoTip",
|
||||
ME_CLC_HIDEINFOTIP = "CLC/HideInfoTip",
|
||||
MS_CLC_SETINFOTIPHOVERTIME = "CLC/SetInfoTipHoverTime",
|
||||
MS_CLC_GETINFOTIPHOVERTIME = "CLC/GetInfoTipHoverTime",
|
||||
ME_CLIST_STATUSMODECHANGE = "CList/StatusModeChange",
|
||||
ME_CLIST_PREBUILDCONTACTMENU = "CList/PreBuildContactMenu",
|
||||
ME_CLIST_DOUBLECLICKED = "CList/DoubleClicked";
|
||||
|
||||
private const string MS_CLIST_ADDEVENT = "CList/AddEvent",
|
||||
MS_CLIST_REMOVEEVENT = "Clist/RemoveEvent";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
private static readonly object SyncObject = new object();
|
||||
|
||||
private EventHandler<ContactListEventArgs<ContactListInfoTip>> InfoTipShowEventHandler,
|
||||
InfoTipHideEventHandler;
|
||||
|
||||
private EventHandler<ProtocolStatusChangeEventArgs> ProtocolStatusChangeEventHandler;
|
||||
private EventHandler<ContactListEventArgs<ContactInfo>> ContactMenuShowingEventHandler;
|
||||
private MirandaEventHandler<ContactListEventArgs<ContactInfo>> ContactDoubleClickedEventHandler;
|
||||
|
||||
private bool ContactSelectionTrackingEnabled;
|
||||
private ContactInfo selectedContact;
|
||||
|
||||
private static readonly Random Random = new Random();
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
internal ContactList() { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public ContactInfo SelectedContact
|
||||
{
|
||||
get
|
||||
{
|
||||
return selectedContact;
|
||||
}
|
||||
}
|
||||
|
||||
public byte? Transparency
|
||||
{
|
||||
get
|
||||
{
|
||||
object alpha = ContactInfo.MeNeutral.ReadSetting("Alpha", "CList", DatabaseSettingType.Byte);
|
||||
|
||||
if (alpha != null)
|
||||
return (byte)alpha;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
ContactInfo.MeNeutral.WriteSetting("Alpha", "CList", value.GetValueOrDefault(byte.MaxValue), DatabaseSettingType.Byte);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TransparencyEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
object enabled = ContactInfo.MeNeutral.ReadSetting("Transparent", "CList", DatabaseSettingType.Byte);
|
||||
|
||||
if (enabled != null)
|
||||
return Convert.ToBoolean((byte)enabled);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
ContactInfo.MeNeutral.WriteSetting("Transparent", "CList", Convert.ToByte(value), DatabaseSettingType.Byte);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
private void FireInfoTipEvent(EventHandler<ContactListEventArgs<ContactListInfoTip>> e, IntPtr lParam)
|
||||
{
|
||||
if (e == null)
|
||||
return;
|
||||
|
||||
ContactListInfoTip infoTip = (ContactListInfoTip)Marshal.PtrToStructure(lParam, typeof(ContactListInfoTip));
|
||||
ContactListEventArgs<ContactListInfoTip> eArgs = new ContactListEventArgs<ContactListInfoTip>(infoTip);
|
||||
|
||||
e(this, eArgs);
|
||||
}
|
||||
|
||||
public event EventHandler<ContactListEventArgs<ContactListInfoTip>> InfoTipShow
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<EventHandler<ContactListEventArgs<ContactListInfoTip>>>(ref InfoTipShowEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_CLC_SHOWINFOTIP,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
FireInfoTipEvent(InfoTipShowEventHandler, lParam);
|
||||
return (int)CallbackResult.Success;
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<EventHandler<ContactListEventArgs<ContactListInfoTip>>>(ref InfoTipShowEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_CLC_SHOWINFOTIP, this.InfoTipShowEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<ContactListEventArgs<ContactListInfoTip>> InfoTipHide
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<EventHandler<ContactListEventArgs<ContactListInfoTip>>>(ref InfoTipHideEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_CLC_HIDEINFOTIP,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
FireInfoTipEvent(InfoTipHideEventHandler, lParam);
|
||||
return (int)CallbackResult.Success;
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<EventHandler<ContactListEventArgs<ContactListInfoTip>>>(ref InfoTipHideEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_CLC_HIDEINFOTIP, this.InfoTipHideEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<ProtocolStatusChangeEventArgs> ProtocolStatusChange
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<EventHandler<ProtocolStatusChangeEventArgs>>(ref ProtocolStatusChangeEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_CLIST_STATUSMODECHANGE,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
string protocolName = lParam == IntPtr.Zero ? null : Translate.ToString(lParam, StringEncoding.Ansi);
|
||||
Protocol protocol = null;
|
||||
|
||||
if (!String.IsNullOrEmpty(protocolName))
|
||||
protocol = new Protocol(protocolName, ProtocolType.Protocol);
|
||||
|
||||
ProtocolStatusChangeEventArgs eArgs = new ProtocolStatusChangeEventArgs(protocol, Translate.ToStatus(wParam));
|
||||
|
||||
if (ProtocolStatusChangeEventHandler != null)
|
||||
ProtocolStatusChangeEventHandler(this, eArgs);
|
||||
|
||||
return (int)CallbackResult.Success;
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<EventHandler<ProtocolStatusChangeEventArgs>>(ref ProtocolStatusChangeEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_CLIST_STATUSMODECHANGE, ProtocolStatusChangeEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<ContactListEventArgs<ContactInfo>> ContactMenuShowing
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<EventHandler<ContactListEventArgs<ContactInfo>>>(ref ContactMenuShowingEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_CLIST_PREBUILDCONTACTMENU,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (ContactMenuShowingEventHandler != null)
|
||||
ContactMenuShowingEventHandler(this, new ContactListEventArgs<ContactInfo>(ContactInfo.FromHandle(wParam)));
|
||||
|
||||
return (int)CallbackResult.Success;
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<EventHandler<ContactListEventArgs<ContactInfo>>>(ref ContactMenuShowingEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_CLIST_PREBUILDCONTACTMENU, ContactMenuShowingEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public event MirandaEventHandler<ContactListEventArgs<ContactInfo>> ContactDoubleClicked
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<MirandaEventHandler<ContactListEventArgs<ContactInfo>>>(ref ContactDoubleClickedEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_CLIST_DOUBLECLICKED,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
bool retValue = InvokeChainCancelable<ContactListEventArgs<ContactInfo>>(ContactDoubleClickedEventHandler, new ContactListEventArgs<ContactInfo>(ContactInfo.FromHandle(wParam)));
|
||||
return Convert.ToInt32(retValue);
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<MirandaEventHandler<ContactListEventArgs<ContactInfo>>>(ref ContactDoubleClickedEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_CLIST_DOUBLECLICKED, ContactDoubleClickedEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
#region Menu
|
||||
|
||||
public void AddMenuItem(MirandaPlugin owner, MenuItemDeclarationAttribute item)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (item == null)
|
||||
throw new ArgumentNullException("item");
|
||||
|
||||
string serviceName = item.IsContactMenuItem ? MirandaServices.MS_CLIST_ADDCONTACTMENUITEM : MirandaServices.MS_CLIST_ADDMAINMENUITEM;
|
||||
|
||||
UnmanagedStructHandle<CLISTMENUITEM> nativeHandle = UnmanagedStructHandle<CLISTMENUITEM>.Empty;
|
||||
CLISTMENUITEM nativeItem = new CLISTMENUITEM(owner, item);
|
||||
|
||||
try
|
||||
{
|
||||
nativeHandle = new UnmanagedStructHandle<CLISTMENUITEM>(ref nativeItem);
|
||||
|
||||
IntPtr handle = (IntPtr)MirandaContext.Current.CallService(serviceName, UIntPtr.Zero, nativeHandle.IntPtr,
|
||||
(owner is StandalonePlugin && !item.IsAdditional));
|
||||
|
||||
item.MirandaHandle = handle;
|
||||
Debug.Assert(handle != IntPtr.Zero);
|
||||
}
|
||||
finally
|
||||
{
|
||||
nativeHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ModifyMenuItem(MirandaPlugin owner, MenuItemDeclarationAttribute menuItem, string text)
|
||||
{
|
||||
return ModifyMenuItem(owner, menuItem, text, MenuItemProperties.None, null, 0, true);
|
||||
}
|
||||
|
||||
public bool ModifyMenuItem(MirandaPlugin owner, MenuItemDeclarationAttribute menuItem, MenuItemProperties flags)
|
||||
{
|
||||
return ModifyMenuItem(owner, menuItem, null, flags, null, 0, true);
|
||||
}
|
||||
|
||||
public bool ModifyMenuItem(MirandaPlugin owner, MenuItemDeclarationAttribute menuItem, HotKeys hotKey)
|
||||
{
|
||||
return ModifyMenuItem(owner, menuItem, null, MenuItemProperties.None, null, hotKey, true);
|
||||
}
|
||||
|
||||
public bool ModifyMenuItem(MirandaPlugin owner, MenuItemDeclarationAttribute menuItem, Icon icon)
|
||||
{
|
||||
return ModifyMenuItem(owner, menuItem, null, MenuItemProperties.None, icon, 0, true);
|
||||
}
|
||||
|
||||
public bool ModifyMenuItem(MirandaPlugin owner, MenuItemDeclarationAttribute menuItem, string text, MenuItemProperties flags, Icon icon, HotKeys hotKey)
|
||||
{
|
||||
return ModifyMenuItem(owner, menuItem, text, flags, icon, hotKey, true);
|
||||
}
|
||||
|
||||
public bool ModifyMenuItem(MirandaPlugin owner, MenuItemDeclarationAttribute menuItem, string text, MenuItemProperties flags, Icon icon, HotKeys hotKey, bool updateItemDescriptor)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (menuItem == null)
|
||||
throw new ArgumentNullException("menuItem");
|
||||
|
||||
if (menuItem.MirandaHandle == IntPtr.Zero)
|
||||
throw new ArgumentException("Invalid menu item handle.");
|
||||
|
||||
UnmanagedStructHandle<CLISTMENUITEM> nativeHandle = UnmanagedStructHandle<CLISTMENUITEM>.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginMenuItemUpdate(menuItem);
|
||||
|
||||
CLISTMENUITEM nativeItem = new CLISTMENUITEM(owner, menuItem);
|
||||
MenuItemModifyFlags modifyFlags = MenuItemModifyFlags.None;
|
||||
|
||||
if (text != null)
|
||||
{
|
||||
modifyFlags |= MenuItemModifyFlags.CMIM_NAME;
|
||||
nativeItem.Text = text;
|
||||
|
||||
if (updateItemDescriptor) menuItem.Text = text;
|
||||
}
|
||||
if (flags != MenuItemProperties.KeepCurrent)
|
||||
{
|
||||
modifyFlags |= MenuItemModifyFlags.CMIM_FLAGS;
|
||||
nativeItem.Flags = (uint)flags;
|
||||
|
||||
if (updateItemDescriptor) menuItem.Flags = flags;
|
||||
}
|
||||
if (icon != null)
|
||||
{
|
||||
modifyFlags |= MenuItemModifyFlags.CMIM_ICON;
|
||||
nativeItem.Icon = icon.Handle;
|
||||
}
|
||||
if (hotKey != 0)
|
||||
{
|
||||
modifyFlags |= MenuItemModifyFlags.CMIM_HOTKEY;
|
||||
nativeItem.HotKey = (uint)hotKey;
|
||||
if (updateItemDescriptor) menuItem.HotKey = hotKey;
|
||||
}
|
||||
|
||||
nativeItem.Flags |= (uint)modifyFlags;
|
||||
|
||||
nativeHandle = new UnmanagedStructHandle<CLISTMENUITEM>(ref nativeItem);
|
||||
bool result = MirandaContext.Current.CallService(MirandaServices.MS_CLIST_MODIFYMENUITEM, (UIntPtr)(uint)menuItem.MirandaHandle, nativeHandle.IntPtr) == 0
|
||||
? true : false;
|
||||
|
||||
Debug.Assert(result);
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new MirandaException(TextResources.ExceptionMsg_ErrorWhileCallingMirandaService + e.Message, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
nativeHandle.Free();
|
||||
SynchronizationHelper.EndUpdate(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI
|
||||
|
||||
public bool ShowBaloonTip(string title, string text, string protocol, ToolTipIcon icon, int timeout)
|
||||
{
|
||||
UnmanagedStructHandle<MIRANDASYSTRAYNOTIFY> nativeHandle = UnmanagedStructHandle<MIRANDASYSTRAYNOTIFY>.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
MIRANDASYSTRAYNOTIFY msn = new MIRANDASYSTRAYNOTIFY(title, text, icon);
|
||||
msn.Timeout = (uint)timeout;
|
||||
msn.Protocol = protocol;
|
||||
|
||||
nativeHandle = new UnmanagedStructHandle<MIRANDASYSTRAYNOTIFY>(ref msn);
|
||||
int result = MirandaContext.Current.CallService(MirandaServices.MS_CLIST_SYSTRAY_NOTIFY, UIntPtr.Zero, nativeHandle.IntPtr);
|
||||
|
||||
bool retValue = (result == 0);
|
||||
Debug.Assert(retValue);
|
||||
|
||||
return retValue;
|
||||
}
|
||||
finally
|
||||
{
|
||||
nativeHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
public bool SetInfoTipHoverTime(int time)
|
||||
{
|
||||
int result = MirandaContext.Current.CallService(MS_CLC_SETINFOTIPHOVERTIME, (UIntPtr)(uint)time, IntPtr.Zero);
|
||||
Debug.Assert(result == 0);
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
public int GetInfoTipHoverTime()
|
||||
{
|
||||
return MirandaContext.Current.CallService(MS_CLC_GETINFOTIPHOVERTIME);
|
||||
}
|
||||
|
||||
public void EnableContactSelectionTracking()
|
||||
{
|
||||
lock (SyncObject)
|
||||
{
|
||||
if (ContactSelectionTrackingEnabled)
|
||||
return;
|
||||
|
||||
ContactMenuShowing += HandleContactSelection;
|
||||
ContactSelectionTrackingEnabled = true;
|
||||
|
||||
MirandaContext.Current.IsolatedModePluginsUnloading += delegate { ContactMenuShowing -= HandleContactSelection; };
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleContactSelection(object sender, ContactListEventArgs<ContactInfo> e)
|
||||
{
|
||||
lock (SyncObject)
|
||||
selectedContact = e.EventData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public IntPtr AddEvent(ContactInfo contact, Icon icon, string serviceToCall, ContactListEventProperties properties, string toolTip)
|
||||
{
|
||||
if (contact == null)
|
||||
throw new ArgumentNullException("contact");
|
||||
|
||||
return AddEvent(contact, icon, serviceToCall, IntPtr.Zero, contact.MirandaHandle, properties, toolTip);
|
||||
}
|
||||
|
||||
public IntPtr AddEvent(ContactInfo contact, Icon icon, string serviceToCall, IntPtr lParamToPass, IntPtr eventToken, ContactListEventProperties properties, string toolTip)
|
||||
{
|
||||
if (contact == null)
|
||||
throw new ArgumentNullException("contact");
|
||||
|
||||
if (icon == null)
|
||||
throw new ArgumentNullException("icon");
|
||||
|
||||
ContactListEvent clistEvent = new ContactListEvent();
|
||||
clistEvent.ContactHandle = contact.MirandaHandle;
|
||||
clistEvent.EventHandle = eventToken;
|
||||
clistEvent.Flags = (uint)properties;
|
||||
clistEvent.IconHandle = icon.Handle;
|
||||
clistEvent.LParam = lParamToPass;
|
||||
clistEvent.ServiceName = serviceToCall;
|
||||
clistEvent.Tooltip = toolTip;
|
||||
|
||||
UnmanagedStructHandle<ContactListEvent> nativeStruct = UnmanagedStructHandle<ContactListEvent>.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
nativeStruct = new UnmanagedStructHandle<ContactListEvent>(ref clistEvent);
|
||||
IntPtr eventHandle = (IntPtr)MirandaContext.Current.CallService(MS_CLIST_ADDEVENT, UIntPtr.Zero, nativeStruct.IntPtr);
|
||||
|
||||
if (eventHandle != IntPtr.Zero)
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_CLIST_ADDEVENT, eventHandle.ToString()));
|
||||
|
||||
return clistEvent.EventHandle;
|
||||
}
|
||||
finally
|
||||
{
|
||||
nativeStruct.Free();
|
||||
}
|
||||
}
|
||||
|
||||
public bool RemoveEvent(ContactInfo contact)
|
||||
{
|
||||
if (contact == null)
|
||||
throw new ArgumentNullException("contact");
|
||||
|
||||
return RemoveEvent(contact, contact.MirandaHandle);
|
||||
}
|
||||
|
||||
public bool RemoveEvent(ContactInfo contact, IntPtr eventToken)
|
||||
{
|
||||
if (contact == null)
|
||||
throw new ArgumentNullException("contact");
|
||||
|
||||
return !Convert.ToBoolean(MirandaContext.Current.CallService(MS_CLIST_REMOVEEVENT, contact.MirandaHandle, eventToken));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
|
||||
public sealed class ContactListEvent
|
||||
{
|
||||
#region Native fields
|
||||
|
||||
private readonly int Size;
|
||||
internal IntPtr ContactHandle;
|
||||
internal IntPtr IconHandle;
|
||||
internal UInt32 Flags;
|
||||
internal IntPtr EventHandle;
|
||||
internal IntPtr lParam;
|
||||
internal string ServiceName;
|
||||
internal string Tooltip;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
internal ContactListEvent()
|
||||
{
|
||||
Size = Marshal.SizeOf(this);
|
||||
}
|
||||
|
||||
public static ContactListEvent FromPointer(IntPtr pClistEvent)
|
||||
{
|
||||
if (pClistEvent == IntPtr.Zero)
|
||||
throw new ArgumentNullException("pClistEventHandle");
|
||||
|
||||
return (ContactListEvent)Marshal.PtrToStructure(pClistEvent, typeof(ContactListEvent));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Managed properties
|
||||
|
||||
public ContactInfo Contact
|
||||
{
|
||||
get { return ContactInfo.FromHandle(ContactHandle); }
|
||||
}
|
||||
|
||||
public IntPtr LParam
|
||||
{
|
||||
get { return lParam; }
|
||||
internal set { lParam = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
// typedef struct {
|
||||
// int cbSize; //size in bytes of this structure
|
||||
// HANDLE hContact; //handle to the contact to put the icon by
|
||||
// HICON hIcon; //icon to flash
|
||||
// DWORD flags; //...of course
|
||||
// union
|
||||
// {
|
||||
// HANDLE hDbEvent; //caller defined but should be unique for hContact
|
||||
// char * lpszProtocol;
|
||||
// };
|
||||
// LPARAM lParam; //caller defined
|
||||
// char *pszService; //name of the service to call on activation
|
||||
// union {
|
||||
// char *pszTooltip; //short description of the event to display as a
|
||||
// TCHAR *ptszTooltip; //tooltip on the system tray
|
||||
// };
|
||||
//} CLISTEVENT;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[Serializable]
|
||||
public class ContactListEventArgs<T> : MirandaEventArgs
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private T eventData;
|
||||
public T EventData
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.eventData;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
internal ContactListEventArgs(T eventData)
|
||||
{
|
||||
this.eventData = eventData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
public struct ContactListInfoTip
|
||||
{
|
||||
#region Native fields
|
||||
|
||||
private int size, isTreeFocused, isGroup;
|
||||
private IntPtr itemPtr;
|
||||
|
||||
private Point point;
|
||||
private Rectangle rectangle;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public bool IsTreeFocused
|
||||
{
|
||||
get { return Convert.ToBoolean(isTreeFocused); }
|
||||
}
|
||||
|
||||
public bool IsGroup
|
||||
{
|
||||
get { return Convert.ToBoolean(isGroup); }
|
||||
}
|
||||
|
||||
public MirandaItem Item
|
||||
{
|
||||
get
|
||||
{
|
||||
return IsGroup ? (MirandaItem)new GroupInfo(itemPtr) : (MirandaItem)ContactInfo.FromHandle(itemPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public Point Point
|
||||
{
|
||||
get { return point; }
|
||||
}
|
||||
|
||||
public Rectangle Rectangle
|
||||
{
|
||||
get { return rectangle; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/*
|
||||
* typedef struct {
|
||||
int cbSize;
|
||||
int isTreeFocused; //so the plugin can provide an option
|
||||
int isGroup; //0 if it's a contact, 1 if it's a group
|
||||
HANDLE hItem; //handle to group or contact
|
||||
POINT ptCursor;
|
||||
RECT rcItem;
|
||||
} CLCINFOTIP;*/
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a base class for cross-domain callable object that operate with Miranda Context.
|
||||
/// </summary>
|
||||
public abstract class ContextWorker : RemoteObject
|
||||
{
|
||||
protected internal ContextWorker() { }
|
||||
|
||||
protected MirandaContext Context
|
||||
{
|
||||
get { return MirandaContext.Current; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents database event information.
|
||||
/// </summary>
|
||||
public class DatabaseEventInfo : IMirandaObject
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string MS_DB_EVENT_GETBLOBSIZE = "DB/Event/GetBlobSize";
|
||||
|
||||
/// <summary>
|
||||
/// DB/Event/Get
|
||||
/// Retrieves all the information stored in hDbEvent
|
||||
/// wParam=(WPARAM)(HANDLE)hDbEvent
|
||||
/// lParam=(LPARAM)(DBEVENTINFO*)&dbe
|
||||
/// hDbEvent should have been returned by db/event/add or db/event/find*event
|
||||
/// Returns 0 on success or nonzero if hDbEvent is invalid
|
||||
/// Don't forget to set dbe.cbSize, dbe.pBlob and dbe.cbBlob before calling this
|
||||
/// service
|
||||
/// The correct value dbe.cbBlob can be got using db/event/getblobsize
|
||||
/// If successful, all the fields of dbe are filled. dbe.cbBlob is set to the
|
||||
/// actual number of bytes retrieved and put in dbe.pBlob
|
||||
/// If dbe.cbBlob is too small, dbe.pBlob is filled up to the size of dbe.cbBlob
|
||||
/// and then dbe.cbBlob is set to the required size of data to go in dbe.pBlob
|
||||
/// On return, dbe.szModule is a pointer to the database module's own internal list
|
||||
/// of modules. Look but don't touch.
|
||||
/// </summary>
|
||||
private const string MS_DB_EVENT_GET = "DB/Event/Get";
|
||||
|
||||
private const string MS_DB_TIME_TIMESTAMPTOSTRING = "DB/Time/TimestampToString";
|
||||
|
||||
/// <summary>
|
||||
/// DB/Event/GetContact
|
||||
/// Retrieves a handle to the contact that owns hDbEvent.
|
||||
/// wParam=(WPARAM)(HANDLE)hDbEvent
|
||||
/// lParam=0
|
||||
/// hDbEvent should have been returned by db/event/add or db/event/find*event
|
||||
/// NULL is a valid return value, meaning, as usual, the user.
|
||||
/// Returns (HANDLE)(-1) if hDbEvent is invalid, or the handle to the contact on
|
||||
/// success
|
||||
/// This service is exceptionally slow. Use only when you have no other choice at
|
||||
/// all.
|
||||
/// </summary>
|
||||
private const string MS_DB_EVENT_GETCONTACT = "DB/Event/GetContact";
|
||||
|
||||
/// <summary>
|
||||
/// DB/Event/GetText (0.7.0+)
|
||||
/// Retrieves the event's text
|
||||
/// wParam=(WPARAM)0 (unused)
|
||||
/// lParam=(LPARAM)(DBEVENTGETTEXT*)egt - pointer to structure with parameters
|
||||
/// egt->dbei should be the valid database event read via MS_DB_EVENT_GET
|
||||
/// egt->datatype = DBVT_WCHAR or DBVT_ASCIIZ or DBVT_TCHAR. If a caller wants to
|
||||
/// suppress Unicode part of event in answer, add DBVTF_DENYUNICODE to this field.
|
||||
/// egt->codepage is any valid codepage, CP_ACP by default.
|
||||
/// Function returns a pointer to a string in the required format.
|
||||
/// This string should be freed by a call of mir_free
|
||||
/// </summary>
|
||||
private const string MS_DB_EVENT_GETTEXT = "DB/Event/GetText";
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DatabaseEventInfo"/> class.
|
||||
/// </summary>
|
||||
protected DatabaseEventInfo() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DatabaseEventInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="mirandaHandle">Event handle.</param>
|
||||
protected DatabaseEventInfo(IntPtr eventHandle)
|
||||
{
|
||||
if (eventHandle == IntPtr.Zero)
|
||||
throw new ArgumentNullException("eventHandle");
|
||||
|
||||
this.mirandaHandle = eventHandle;
|
||||
FromHandle(eventHandle, out type, out flags, out data, out owningModule, out timestamp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DatabaseEventInfo"/> from an event handle.
|
||||
/// </summary>
|
||||
/// <param name="mirandaHandle">Event handle.</param>
|
||||
/// <returns>Database event info.</returns>
|
||||
public static DatabaseEventInfo FromHandle(IntPtr eventHandle)
|
||||
{
|
||||
return new DatabaseEventInfo(eventHandle);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initializers
|
||||
|
||||
/// <summary>
|
||||
/// Gets the event information based on its handle.
|
||||
/// </summary>
|
||||
/// <param name="eventHandle">Event handle.</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>
|
||||
public static void FromHandle(IntPtr eventHandle, out DatabaseEventType type, out DatabaseEventProperties flags, out string data, out Protocol owningModule, out DateTime timestamp)
|
||||
{
|
||||
InteropBuffer buffer = null;
|
||||
|
||||
try
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
DBEVENTINFO dbEventInfo;
|
||||
PrepareDbEventInfo(eventHandle, out dbEventInfo, out buffer);
|
||||
|
||||
GetEventInfo(ref dbEventInfo, eventHandle, buffer, out type, out flags, out data, out owningModule, out timestamp);
|
||||
}
|
||||
}
|
||||
catch (MirandaException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException(TextResources.ExceptionMsg_CannotFinishMarshaling, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
buffer.Unlock();
|
||||
InteropBufferPool.ReleaseBuffer(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the instance by marshaling data from a <see cref="DBEVENTINFO"/> pointer.
|
||||
/// </summary>
|
||||
/// <param name="pDbEventInfo"><see cref="DBEVENTINFO"/> pointer.</param>
|
||||
private void MarshalEventInfo(IntPtr pDbEventInfo)
|
||||
{
|
||||
DBEVENTINFO info = (DBEVENTINFO)Marshal.PtrToStructure(pDbEventInfo, typeof(DBEVENTINFO));
|
||||
|
||||
// Get an appropriately size buffer for the blob
|
||||
InteropBuffer buffer = InteropBufferPool.AcquireBuffer((int)info.BlobSize);
|
||||
|
||||
try
|
||||
{
|
||||
buffer.Lock();
|
||||
GetEventInfo(ref info, IntPtr.Zero, buffer, out type, out flags, out data, out owningModule, out timestamp);
|
||||
}
|
||||
finally
|
||||
{
|
||||
buffer.Unlock();
|
||||
InteropBufferPool.ReleaseBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// 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>
|
||||
/// 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>
|
||||
/// 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 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;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private IntPtr mirandaHandle;
|
||||
public IntPtr MirandaHandle
|
||||
{
|
||||
get { return mirandaHandle; }
|
||||
}
|
||||
|
||||
private Protocol owningModule;
|
||||
public Protocol OwningModule
|
||||
{
|
||||
get { return owningModule; }
|
||||
}
|
||||
|
||||
private DateTime timestamp;
|
||||
public DateTime Timestamp
|
||||
{
|
||||
get { return timestamp; }
|
||||
}
|
||||
|
||||
private DatabaseEventProperties flags;
|
||||
public DatabaseEventProperties Flags
|
||||
{
|
||||
get { return flags; }
|
||||
}
|
||||
|
||||
private DatabaseEventType type;
|
||||
public DatabaseEventType Type
|
||||
{
|
||||
get { return type; }
|
||||
}
|
||||
|
||||
private string data;
|
||||
public string Data
|
||||
{
|
||||
get { return data; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Marshals the <see cref="DatabaseEventInfo"/> from a <see cref="DBEVENTINFO"/> struct pointer.
|
||||
/// </summary>
|
||||
/// <param name="pDbEventInfo"><see cref="DBEVENTINFO"/> struct pointer.</param>
|
||||
/// <returns>Event info.</returns>
|
||||
internal static DatabaseEventInfo FromPointer(IntPtr pDbEventInfo)
|
||||
{
|
||||
DatabaseEventInfo info = new DatabaseEventInfo();
|
||||
info.MarshalEventInfo(pDbEventInfo);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the handle of the contact owning this event. This method is very slow, use wisely.
|
||||
/// </summary>
|
||||
/// <returns>Associated contact handle.</returns>
|
||||
public IntPtr GetContactHandle()
|
||||
{
|
||||
return GetContactHandle(mirandaHandle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the handle of the contact owning this event. This method is very slow, use wisely.
|
||||
/// </summary>
|
||||
/// <param name="eventHandle">Event handle to get the contact handle for.</param>
|
||||
/// <returns>Associated contact handle.</returns>
|
||||
public static IntPtr GetContactHandle(IntPtr eventHandle)
|
||||
{
|
||||
if (eventHandle == IntPtr.Zero)
|
||||
throw new ArgumentNullException("eventHandle");
|
||||
|
||||
int contactHandle = MirandaContext.Current.CallService(MS_DB_EVENT_GETCONTACT, eventHandle, IntPtr.Zero);
|
||||
|
||||
if (contactHandle == -1)
|
||||
throw new ArgumentException(TextResources.ExceptionMsg_InvalidHandle, "eventHandle");
|
||||
|
||||
return (IntPtr)contactHandle;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using Virtuoso.Hyphen;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Virtuoso.Miranda.Plugins.Collections;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[CLSCompliant(false)]
|
||||
public sealed class EventHandle : MirandaObject
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private readonly MirandaPlugin owner;
|
||||
internal MirandaPlugin Owner
|
||||
{
|
||||
get { return owner; }
|
||||
}
|
||||
|
||||
private readonly string eventName;
|
||||
public string EventName
|
||||
{
|
||||
get { return eventName; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
internal EventHandle(MirandaPlugin owner, string eventName, IntPtr handle)
|
||||
{
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new ArgumentNullException("handle");
|
||||
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (eventName == null)
|
||||
throw new ArgumentNullException("eventName");
|
||||
|
||||
this.owner = owner;
|
||||
this.MirandaHandle = handle;
|
||||
this.eventName = eventName;
|
||||
|
||||
List<EventHandle> eventHandles = owner.Descriptor.EventHandles;
|
||||
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginCollectionUpdate(eventHandles);
|
||||
eventHandles.Add(this);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(eventHandles);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public int FireEvent()
|
||||
{
|
||||
return FireEvent(UIntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
|
||||
public int FireEvent(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
MirandaPluginLink link = MirandaContext.Current.PluginLink;
|
||||
|
||||
lock (link)
|
||||
return link.NativePluginLink.NotifyEventHooks(MirandaHandle, wParam, lParam);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public void SetDefaultSubscriber(Callback subscriber)
|
||||
{
|
||||
if (subscriber == null)
|
||||
throw new ArgumentNullException("subscriber");
|
||||
|
||||
MirandaPluginLink link = MirandaContext.Current.PluginLink;
|
||||
|
||||
lock (link)
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((result = link.NativePluginLink.SetHookDefaultForHookableEvent(MirandaHandle, subscriber)) != 0)
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, "SetHookDefaultForHookableEvent", result.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||
public sealed class EventHookAttribute : HookAttribute
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private string eventName;
|
||||
public string EventName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.eventName;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.eventName = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal override string HookName
|
||||
{
|
||||
get { return EventName; }
|
||||
}
|
||||
|
||||
internal override HookType HookType
|
||||
{
|
||||
get { return HookType.EventHook; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
public EventHookAttribute(string eventName)
|
||||
{
|
||||
if (eventName == null)
|
||||
throw new ArgumentNullException("eventName");
|
||||
|
||||
this.eventName = eventName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Collections;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using Virtuoso.Hyphen;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public static class EventManager
|
||||
{
|
||||
[CLSCompliant(false)]
|
||||
public static void CreateEventHook(string eventName, Callback callback, MirandaPlugin owner)
|
||||
{
|
||||
if (String.IsNullOrEmpty(eventName))
|
||||
throw new ArgumentNullException("eventName");
|
||||
|
||||
if (callback == null)
|
||||
throw new ArgumentNullException("callback");
|
||||
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (!owner.Initialized)
|
||||
throw new InvalidOperationException(TextResources.ExceptionMsg_PluginNotInitialized);
|
||||
|
||||
HookDescriptorCollection collection = owner.Descriptor.EventHooks;
|
||||
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginPluginUpdate(owner);
|
||||
SynchronizationHelper.BeginCollectionUpdate(collection);
|
||||
|
||||
HookDescriptor descriptor = HookDescriptor.SetUpAndStore(collection, eventName, owner.Descriptor, callback, HookType.EventHook);
|
||||
descriptor.RegisteredManually = true;
|
||||
|
||||
HookManager.CreateHook(descriptor);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(owner);
|
||||
SynchronizationHelper.EndUpdate(collection);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveEventHook(string eventName, MirandaPlugin owner)
|
||||
{
|
||||
if (String.IsNullOrEmpty(eventName))
|
||||
throw new ArgumentNullException("eventName");
|
||||
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (!owner.Initialized)
|
||||
throw new InvalidOperationException(TextResources.ExceptionMsg_PluginNotInitialized);
|
||||
|
||||
HookDescriptorCollection collection = owner.Descriptor.EventHooks;
|
||||
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginCollectionUpdate(collection);
|
||||
HookDescriptor descriptor = null;
|
||||
|
||||
if ((descriptor = owner.Descriptor.EventHooks.Find(eventName)) == null)
|
||||
return;
|
||||
|
||||
HookManager.DestroyHook(descriptor);
|
||||
collection.Remove(descriptor);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(collection);
|
||||
}
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static EventHandle CreateEvent(string eventName, MirandaPlugin owner)
|
||||
{
|
||||
return CreateEvent(eventName, owner, null);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static EventHandle CreateEvent(string eventName, MirandaPlugin owner, Callback defaultSubscriber)
|
||||
{
|
||||
if (String.IsNullOrEmpty(eventName))
|
||||
throw new ArgumentNullException("eventName");
|
||||
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (!owner.Initialized)
|
||||
throw new InvalidOperationException(TextResources.ExceptionMsg_PluginNotInitialized);
|
||||
|
||||
if (ServiceManager.ServiceExists(eventName))
|
||||
throw new ArgumentException("eventName");
|
||||
|
||||
EventHandle handle = new EventHandle(owner, eventName, MirandaContext.Current.PluginLink.NativePluginLink.CreateHookableEvent(eventName));
|
||||
|
||||
if (defaultSubscriber != null)
|
||||
handle.SetDefaultSubscriber(defaultSubscriber);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
public static void RemoveEvent(EventHandle eventHandle)
|
||||
{
|
||||
if (eventHandle == null)
|
||||
throw new ArgumentNullException("eventHandle");
|
||||
|
||||
MirandaPluginLink link = MirandaContext.Current.PluginLink;
|
||||
|
||||
if (eventHandle.MirandaHandle != IntPtr.Zero)
|
||||
{
|
||||
int result;
|
||||
if ((result = link.NativePluginLink.DestroyHookableEvent(eventHandle.MirandaHandle)) != 0)
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, "DestroyHookableEvent", result.ToString()));
|
||||
|
||||
eventHandle.MirandaHandle = IntPtr.Zero;
|
||||
EventHandleCollection handles = eventHandle.Owner.Descriptor.EventHandles;
|
||||
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginCollectionUpdate(handles);
|
||||
handles.Remove(eventHandle);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(handles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public abstract class EventPublisher
|
||||
{
|
||||
internal EventPublisher() { }
|
||||
|
||||
protected bool InvokeChainCancelable<TEventArgs>(MirandaEventHandler<TEventArgs> handler, TEventArgs eventArgs) where TEventArgs : MirandaEventArgs
|
||||
{
|
||||
return InvokeChainCancelable<TEventArgs>(handler, this, eventArgs);
|
||||
}
|
||||
|
||||
public static bool InvokeChainCancelable<TEventArgs>(MirandaEventHandler<TEventArgs> handler, object sender, TEventArgs eventArgs) where TEventArgs : MirandaEventArgs
|
||||
{
|
||||
bool retValue = EventResult.HonourEventChain;
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
foreach (MirandaEventHandler<TEventArgs> del in handler.GetInvocationList())
|
||||
{
|
||||
if ((retValue = del(sender, eventArgs)) == EventResult.BreakEventChain)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public sealed class GroupInfo : MirandaItem
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private const string MS_CLIST_GROUPGETNAME = "CList/GroupGetName";
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
internal GroupInfo(IntPtr handle) : base(handle, ItemType.Group) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
IntPtr pName = (IntPtr)MirandaContext.Current.CallService(MS_CLIST_GROUPGETNAME, MirandaHandle, IntPtr.Zero);
|
||||
Debug.Assert(pName != IntPtr.Zero);
|
||||
|
||||
if (pName != IntPtr.Zero)
|
||||
return Marshal.PtrToStringAnsi(pName);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe bool IsExpanded
|
||||
{
|
||||
get
|
||||
{
|
||||
int expanded = 0;
|
||||
|
||||
IntPtr pName = (IntPtr)MirandaContext.Current.CallServiceUnsafe(MS_CLIST_GROUPGETNAME, MirandaHandle.ToPointer(), &expanded);
|
||||
Debug.Assert(pName != IntPtr.Zero);
|
||||
|
||||
if (pName != IntPtr.Zero)
|
||||
return Convert.ToBoolean(expanded);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public abstract class HookAttribute : Attribute
|
||||
{
|
||||
protected internal HookAttribute() { }
|
||||
|
||||
internal abstract string HookName { get; }
|
||||
|
||||
internal abstract HookType HookType { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using Virtuoso.Hyphen;
|
||||
using Virtuoso.Miranda.Plugins.Forms;
|
||||
using Virtuoso.Hyphen.Mini;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
internal sealed class HookDescriptor : IMirandaObject, IDescriptor
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private string name;
|
||||
private IntPtr handle;
|
||||
|
||||
private Callback callback, callbackStub;
|
||||
private HookType hookType;
|
||||
|
||||
private PluginDescriptor owner;
|
||||
private bool registeredManually;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctor
|
||||
|
||||
public HookDescriptor(string name, PluginDescriptor owner, Callback callback, HookType type)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name))
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (callback == null)
|
||||
throw new ArgumentNullException("callback");
|
||||
|
||||
this.callbackStub = SafeCallbackStub;
|
||||
|
||||
this.name = name;
|
||||
this.owner = owner;
|
||||
this.callback = callback;
|
||||
this.hookType = type;
|
||||
}
|
||||
|
||||
public static HookDescriptor SetUpAndStore(IList<HookDescriptor> targetContainer, string name, PluginDescriptor owner, Callback callback, HookType type)
|
||||
{
|
||||
if (targetContainer == null)
|
||||
throw new ArgumentNullException("targetContainer");
|
||||
|
||||
HookDescriptor descriptor = new HookDescriptor(name, owner, callback, type);
|
||||
targetContainer.Add(descriptor);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public static HookDescriptor SetUpAndStore(IDictionary<string, HookDescriptor> targetContainer, string name, PluginDescriptor owner, Callback callback, HookType type)
|
||||
{
|
||||
return SetUpAndStore<string>(targetContainer, name, name, owner, callback, type);
|
||||
}
|
||||
|
||||
public static HookDescriptor SetUpAndStore<T>(IDictionary<T, HookDescriptor> targetContainer, T key, string name, PluginDescriptor owner, Callback callback, HookType type)
|
||||
{
|
||||
if (targetContainer == null)
|
||||
throw new ArgumentNullException("targetContainer");
|
||||
|
||||
HookDescriptor descriptor = new HookDescriptor(name, owner, callback, type);
|
||||
targetContainer.Add(key, descriptor);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private int SafeCallbackStub(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
try
|
||||
{
|
||||
return callback(wParam, lParam);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MirandaPlugin.GetExceptionHandler(owner).HandleException(e, owner);
|
||||
return (int)CallbackResult.Failure;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (name.GetHashCode() + callback.Method.Name.GetHashCode() + (int)hookType);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
HookDescriptor other = obj as HookDescriptor;
|
||||
|
||||
if (other == null)
|
||||
return false;
|
||||
|
||||
return GetHashCode() == other.GetHashCode();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
public IntPtr MirandaHandle
|
||||
{
|
||||
get { return handle; }
|
||||
internal set { handle = value; }
|
||||
}
|
||||
|
||||
public Callback Callback
|
||||
{
|
||||
get { return callbackStub; }
|
||||
}
|
||||
|
||||
public HookType HookType
|
||||
{
|
||||
get { return hookType; }
|
||||
}
|
||||
|
||||
public PluginDescriptor Owner
|
||||
{
|
||||
get { return owner; }
|
||||
}
|
||||
|
||||
public bool RegisteredManually
|
||||
{
|
||||
get { return registeredManually; }
|
||||
set { registeredManually = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Hyphen;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
internal static class HookManager
|
||||
{
|
||||
public static void CreateHooks(params HookDescriptor[] hooks)
|
||||
{
|
||||
if (hooks == null)
|
||||
throw new ArgumentNullException("hooks");
|
||||
|
||||
if (hooks.Length == 0)
|
||||
return;
|
||||
|
||||
foreach (HookDescriptor hook in hooks)
|
||||
CreateHook(hook);
|
||||
}
|
||||
|
||||
public static void CreateHook(HookDescriptor hook)
|
||||
{
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginDescriptorUpdate(hook);
|
||||
|
||||
switch (hook.HookType)
|
||||
{
|
||||
case HookType.EventHook:
|
||||
{
|
||||
HookEvent(hook);
|
||||
break;
|
||||
}
|
||||
case HookType.ServiceFunction:
|
||||
{
|
||||
CreateServiceFunction(hook);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentException("descriptor");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(hook);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateServiceFunction(HookDescriptor hook)
|
||||
{
|
||||
if (!ServiceManager.ServiceExists(hook.Name))
|
||||
{
|
||||
hook.MirandaHandle = MirandaContext.Current.PluginLink.NativePluginLink.CreateServiceFunction(hook.Name, hook.Callback);
|
||||
|
||||
if (hook.MirandaHandle == IntPtr.Zero)
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable1_ServiceFunctionCreationFailed, hook.Name));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!hook.Owner.ServiceFunctions.Exists(delegate(HookDescriptor _hook)
|
||||
{
|
||||
return _hook.Equals(hook) && _hook.MirandaHandle != IntPtr.Zero;
|
||||
}))
|
||||
throw new InvalidOperationException(String.Format(TextResources.ExceptionMsg_Formatable1_ServiceFunctionAlreadyExists, hook.Name));
|
||||
}
|
||||
}
|
||||
|
||||
private static void HookEvent(HookDescriptor hook)
|
||||
{
|
||||
hook.MirandaHandle = MirandaContext.Current.PluginLink.NativePluginLink.HookEvent(hook.Name, hook.Callback);
|
||||
|
||||
if (hook.MirandaHandle == IntPtr.Zero)
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable1_EventHookingFailed, hook.Name));
|
||||
}
|
||||
|
||||
public static void DestroyHook(HookDescriptor hook)
|
||||
{
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginDescriptorUpdate(hook);
|
||||
|
||||
switch (hook.HookType)
|
||||
{
|
||||
case HookType.EventHook:
|
||||
{
|
||||
UnhookEvent(hook);
|
||||
break;
|
||||
}
|
||||
case HookType.ServiceFunction:
|
||||
{
|
||||
DestroyServiceFunction(hook);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentException("descriptor");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(hook);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UnhookEvent(HookDescriptor descriptor)
|
||||
{
|
||||
if (descriptor == null)
|
||||
throw new ArgumentNullException("descriptor");
|
||||
|
||||
if (descriptor.HookType != HookType.EventHook)
|
||||
throw new ArgumentOutOfRangeException("descriptor");
|
||||
|
||||
if (descriptor.MirandaHandle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginDescriptorUpdate(descriptor);
|
||||
|
||||
int result = MirandaContext.Current.PluginLink.NativePluginLink.UnhookEvent(descriptor.MirandaHandle);
|
||||
Debug.Assert(result == 0);
|
||||
|
||||
descriptor.MirandaHandle = IntPtr.Zero;
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DestroyServiceFunction(HookDescriptor descriptor)
|
||||
{
|
||||
if (descriptor == null)
|
||||
throw new ArgumentNullException("descriptor");
|
||||
|
||||
if (descriptor.HookType != HookType.ServiceFunction)
|
||||
throw new ArgumentOutOfRangeException("descriptor");
|
||||
|
||||
if (descriptor.MirandaHandle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginDescriptorUpdate(descriptor);
|
||||
|
||||
int result = MirandaContext.Current.PluginLink.NativePluginLink.DestroyServiceFunction(descriptor.MirandaHandle);
|
||||
Debug.Assert(result == 0);
|
||||
|
||||
descriptor.MirandaHandle = IntPtr.Zero;
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
internal enum HookType
|
||||
{
|
||||
Undefined,
|
||||
EventHook,
|
||||
ServiceFunction,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public interface IMirandaObject
|
||||
{
|
||||
IntPtr MirandaHandle { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public interface ISettingOwner
|
||||
{
|
||||
string Name { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public interface IStringResolver
|
||||
{
|
||||
string ResolveString(string stringToResolve, string tag);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public static class LanguagePack
|
||||
{
|
||||
#region Enums
|
||||
|
||||
private enum LanguagePackEncoding : ushort
|
||||
{
|
||||
Ansi = 0,
|
||||
Unicode = 0x1000
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
|
||||
private const string MS_LANGPACK_TRANSLATESTRING = "LangPack/TranslateString";
|
||||
|
||||
#endregion
|
||||
|
||||
#region FromPointer methods
|
||||
|
||||
public static string TranslateString(string str)
|
||||
{
|
||||
if (String.IsNullOrEmpty(str))
|
||||
return str;
|
||||
|
||||
UnmanagedStringHandle stringHandle = UnmanagedStringHandle.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
StringEncoding mirandaEncoding = MirandaEnvironment.MirandaStringEncoding;
|
||||
LanguagePackEncoding encoding = (mirandaEncoding == StringEncoding.Unicode ? LanguagePackEncoding.Unicode : LanguagePackEncoding.Ansi);
|
||||
|
||||
stringHandle = new UnmanagedStringHandle(str, mirandaEncoding);
|
||||
IntPtr translatedPtr = (IntPtr)MirandaContext.Current.CallService(MS_LANGPACK_TRANSLATESTRING, (UIntPtr)encoding, stringHandle.IntPtr);
|
||||
|
||||
return translatedPtr == stringHandle.IntPtr ? str : Translate.ToString(translatedPtr, mirandaEncoding);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new MirandaException(TextResources.ExceptionMsg_ErrorWhileCallingMirandaService, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
stringHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public class LanguagePackStringResolver : IStringResolver
|
||||
{
|
||||
public LanguagePackStringResolver() { }
|
||||
|
||||
public string ResolveString(string stringToResolve, string tag)
|
||||
{
|
||||
return LanguagePack.TranslateString(stringToResolve);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Threading;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a late-binded master subscriber of Miranda events.
|
||||
/// </summary>
|
||||
internal static class LazyEventBinder
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static readonly Dictionary<string, HookDescriptor> EventHandlerDescriptorsTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
static LazyEventBinder()
|
||||
{
|
||||
EventHandlerDescriptorsTable = new Dictionary<string, HookDescriptor>(3);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Management methods
|
||||
|
||||
public static void AttachDelegate<T>(ref T destination, T value) where T : class
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (!typeof(T).IsSubclassOf(typeof(Delegate)))
|
||||
throw new ArgumentException("T");
|
||||
|
||||
destination = Delegate.Combine(destination as Delegate, value as Delegate) as T;
|
||||
}
|
||||
|
||||
public static void DetachDelegate<T>(ref T destination, T value) where T : class
|
||||
{
|
||||
if (!typeof(T).IsSubclassOf(typeof(Delegate)))
|
||||
throw new ArgumentException("T");
|
||||
|
||||
destination = Delegate.Remove(destination as Delegate, value as Delegate) as T;
|
||||
}
|
||||
|
||||
public static void HookMirandaEvent(string eventName, Callback callback)
|
||||
{
|
||||
lock (EventHandlerDescriptorsTable)
|
||||
{
|
||||
if (EventHandlerDescriptorsTable.ContainsKey(eventName))
|
||||
return;
|
||||
|
||||
HookDescriptor descriptor = HookDescriptor.SetUpAndStore(EventHandlerDescriptorsTable, eventName, MirandaPlugin.Hyphen.Singleton.Descriptor, callback, HookType.EventHook);
|
||||
HookManager.CreateHook(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnhookMirandaEvent(string eventName, Delegate callback)
|
||||
{
|
||||
if (callback != null)
|
||||
return;
|
||||
|
||||
lock (EventHandlerDescriptorsTable)
|
||||
{
|
||||
if (!EventHandlerDescriptorsTable.ContainsKey(eventName))
|
||||
return;
|
||||
|
||||
int result = MirandaContext.Current.PluginLink.NativePluginLink.UnhookEvent(EventHandlerDescriptorsTable[eventName].MirandaHandle);
|
||||
Debug.Assert(result == 0);
|
||||
|
||||
EventHandlerDescriptorsTable.Remove(eventName);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||
public sealed class MenuItemDeclarationAttribute : Attribute, IMirandaObject
|
||||
{
|
||||
#region Fields & Properties
|
||||
|
||||
private static readonly Type StringResolverType = typeof(IStringResolver);
|
||||
|
||||
private string text;
|
||||
public string Text
|
||||
{
|
||||
get { return text; }
|
||||
set { text = value; }
|
||||
}
|
||||
|
||||
private MenuItemProperties flags;
|
||||
public MenuItemProperties Flags
|
||||
{
|
||||
get { return flags; }
|
||||
set { flags = value; }
|
||||
}
|
||||
|
||||
private int position, popUpPosition;
|
||||
public int PopUpPosition
|
||||
{
|
||||
get { return popUpPosition; }
|
||||
set { popUpPosition = value; }
|
||||
}
|
||||
public int Position
|
||||
{
|
||||
get { return position; }
|
||||
set { position = value; }
|
||||
}
|
||||
|
||||
private bool useEmbeddedIcon;
|
||||
public bool UseEmbeddedIcon
|
||||
{
|
||||
get { return useEmbeddedIcon; }
|
||||
set { useEmbeddedIcon = value; }
|
||||
}
|
||||
|
||||
private bool hasIcon;
|
||||
public bool HasIcon
|
||||
{
|
||||
get { return hasIcon; }
|
||||
set { hasIcon = value; }
|
||||
}
|
||||
|
||||
private string iconID;
|
||||
public string IconID
|
||||
{
|
||||
get { return iconID; }
|
||||
set { iconID = value; }
|
||||
}
|
||||
|
||||
private string service;
|
||||
public string Service
|
||||
{
|
||||
get { return service; }
|
||||
internal set { service = value; }
|
||||
}
|
||||
|
||||
private string popUpMenu;
|
||||
public string PopUpMenu
|
||||
{
|
||||
get { return popUpMenu; }
|
||||
}
|
||||
|
||||
private string owningModule;
|
||||
public string OwningModule
|
||||
{
|
||||
get { return owningModule; }
|
||||
set { owningModule = value; }
|
||||
}
|
||||
|
||||
private HotKeys hotKey;
|
||||
public HotKeys HotKey
|
||||
{
|
||||
get { return hotKey; }
|
||||
set { hotKey = value; }
|
||||
}
|
||||
|
||||
private Type stringResolver;
|
||||
public Type StringResolver
|
||||
{
|
||||
get { return stringResolver; }
|
||||
}
|
||||
|
||||
private string tag;
|
||||
public string Tag
|
||||
{
|
||||
get { return tag; }
|
||||
set { tag = value; }
|
||||
}
|
||||
|
||||
private bool isContactMenuItem;
|
||||
public bool IsContactMenuItem
|
||||
{
|
||||
get { return isContactMenuItem; }
|
||||
set { isContactMenuItem = value; }
|
||||
}
|
||||
|
||||
private IntPtr mirandaHandle;
|
||||
public IntPtr MirandaHandle
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.mirandaHandle;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
this.mirandaHandle = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool isAdditional;
|
||||
public bool IsAdditional
|
||||
{
|
||||
get { return isAdditional; }
|
||||
set { isAdditional = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
public MenuItemDeclarationAttribute(string text) : this(text, null, null, null) { }
|
||||
|
||||
public MenuItemDeclarationAttribute(string text, Type stringResolver) : this(text, null, stringResolver) { }
|
||||
|
||||
public MenuItemDeclarationAttribute(string text, string service) : this(text, null, service, null) { }
|
||||
|
||||
public MenuItemDeclarationAttribute(string text, string popUpMenu, string service) : this(text, popUpMenu, service, null) { }
|
||||
|
||||
public MenuItemDeclarationAttribute(string text, string service, Type stringResolver) : this(text, null, service, stringResolver) { }
|
||||
|
||||
public MenuItemDeclarationAttribute(string text, string popUpMenu, string service, Type stringResolver)
|
||||
{
|
||||
if (text == null)
|
||||
throw new ArgumentNullException("text");
|
||||
|
||||
this.text = text;
|
||||
this.service = (service == null ? String.Empty : service);
|
||||
this.popUpMenu = popUpMenu;
|
||||
this.stringResolver = stringResolver;
|
||||
|
||||
/* m_clist.h
|
||||
* WARNING: do not use Translate(TS) for p(t)szName or p(t)szPopupName as they
|
||||
are translated by the core, which may lead to double translation. */
|
||||
if (stringResolver != null && stringResolver.GetType() != typeof(LanguagePackStringResolver))
|
||||
ResolveStrings(text, popUpMenu, stringResolver);
|
||||
}
|
||||
|
||||
private void ResolveStrings(string text, string popUpMenu, Type stringResolver)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (stringResolver != null && stringResolver.GetInterface(StringResolverType.FullName) != null)
|
||||
{
|
||||
IStringResolver resolver = null;
|
||||
StringResolverCache cache = StringResolverCache.Singleton;
|
||||
|
||||
lock (cache)
|
||||
{
|
||||
if (!cache.TryGetValue(stringResolver, out resolver))
|
||||
{
|
||||
resolver = (IStringResolver)Activator.CreateInstance(stringResolver, true);
|
||||
|
||||
if (resolver == null)
|
||||
throw new TypeLoadException(stringResolver.FullName);
|
||||
else
|
||||
cache.Add(stringResolver, resolver);
|
||||
}
|
||||
}
|
||||
|
||||
this.text = resolver.ResolveString(text, tag);
|
||||
this.popUpMenu = resolver.ResolveString(popUpMenu, tag);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new FusionException(String.Format(TextResources.ExceptionMsg_Formatable1_CannotLoadStringResolver, stringResolver.FullName), null, null, null, e);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[Serializable]
|
||||
public class MirandaContactEventArgs : MirandaEventArgs
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private readonly ContactInfo contactInfo;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
public MirandaContactEventArgs(ContactInfo contactInfo)
|
||||
{
|
||||
if (contactInfo == null)
|
||||
throw new ArgumentNullException("contactInfo");
|
||||
|
||||
this.contactInfo = contactInfo;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public ContactInfo ContactInfo
|
||||
{
|
||||
get { return contactInfo; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[Serializable]
|
||||
public class MirandaContactSettingEventArgs : MirandaContactEventArgs
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private string settingName;
|
||||
public string SettingName
|
||||
{
|
||||
get { return settingName; }
|
||||
}
|
||||
|
||||
private string settingOwner;
|
||||
public string SettingOwner
|
||||
{
|
||||
get { return settingOwner; }
|
||||
}
|
||||
|
||||
private object value;
|
||||
public object Value
|
||||
{
|
||||
get { return value; }
|
||||
}
|
||||
|
||||
private DatabaseSettingType valueType;
|
||||
public DatabaseSettingType ValueType
|
||||
{
|
||||
get { return valueType; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
public MirandaContactSettingEventArgs(ContactInfo contactInfo, string name, string owner, object value, DatabaseSettingType valueType)
|
||||
: base(contactInfo)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name))
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
this.settingName = name;
|
||||
this.settingOwner = owner;
|
||||
this.value = value;
|
||||
this.valueType = valueType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using Virtuoso.Miranda.Plugins.Collections;
|
||||
using System.Collections.ObjectModel;
|
||||
using Virtuoso.Hyphen;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public sealed class MirandaContext
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string MS_SYSTEM_GETVERSIONTEXT = "Miranda/System/GetVersionText";
|
||||
|
||||
/// <summary>
|
||||
/// Returns Miranda's RTL/CRT function poiners to malloc() free() realloc() -- 0.1.2.2+
|
||||
/// This is useful for preallocation of memory for use with Miranda's services
|
||||
/// that Miranda can free -- or reallocation of a block of memory passed with a service.
|
||||
/// Do not use with memory unless it is explicitly expected the memory *can*
|
||||
/// or *shall* be used in this way. The passed structure is expected to have it's .cbSize initialised
|
||||
/// wParam=0, lParam = (LPARAM) &MM_INTERFACE.
|
||||
/// </summary>
|
||||
private const string MS_SYSTEM_GET_MMI = "Miranda/System/GetMMI";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
private static MirandaContext singleton;
|
||||
private PluginManagerBase pluginManager;
|
||||
|
||||
private readonly ServiceCallInterceptionManager serviceInterceptors;
|
||||
private readonly MirandaDatabase mirandaDatabase;
|
||||
private ProtocolDictionary protocols;
|
||||
private readonly MirandaPluginLink pluginLink;
|
||||
private readonly ContactList contactList;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
private MirandaContext(PluginManagerBase pluginManager, MirandaPluginLink mirandaLink, bool skipContextInfo)
|
||||
{
|
||||
if (mirandaLink == null)
|
||||
throw new ArgumentNullException("mirandaLink");
|
||||
|
||||
this.pluginManager = pluginManager;
|
||||
this.mirandaDatabase = new MirandaDatabase();
|
||||
this.pluginLink = mirandaLink;
|
||||
this.contactList = new ContactList();
|
||||
this.serviceInterceptors = new ServiceCallInterceptionManager();
|
||||
|
||||
GetMMInterface();
|
||||
|
||||
PopulateEnvironmentInformation();
|
||||
|
||||
if (!skipContextInfo)
|
||||
PopulateContextInformation();
|
||||
else
|
||||
this.protocols = new ProtocolDictionary(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a context from a plugin link.
|
||||
/// </summary>
|
||||
/// <param name="mirandaLink"></param>
|
||||
/// <param name="skipContextPopulation"></param>
|
||||
internal static void InitializeCurrent(MirandaPluginLink mirandaLink, bool skipContextPopulation)
|
||||
{
|
||||
InitializeCurrent(mirandaLink, null, skipContextPopulation);
|
||||
}
|
||||
|
||||
internal static void InitializeCurrent(MirandaPluginLink mirandaLink, PluginManagerBase pluginManager)
|
||||
{
|
||||
InitializeCurrent(mirandaLink, pluginManager, false);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
internal static void InitializeCurrent(MirandaPluginLink mirandaLink, PluginManagerBase pluginManager, bool skipContextPopulation)
|
||||
{
|
||||
if (singleton == null)
|
||||
singleton = new MirandaContext(pluginManager, mirandaLink, skipContextPopulation);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
internal static void InitializeCurrent(MirandaContext context)
|
||||
{
|
||||
if (context == null)
|
||||
throw new ArgumentNullException("context");
|
||||
|
||||
if (singleton == null)
|
||||
singleton = context;
|
||||
else
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
internal static void InvalidateCurrent()
|
||||
{
|
||||
if (Initialized)
|
||||
{
|
||||
singleton.DetachPluginManager();
|
||||
singleton = null;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
internal void AssociatePluginManager(PluginManagerBase manager)
|
||||
{
|
||||
if (manager == null)
|
||||
throw new ArgumentNullException("manager");
|
||||
|
||||
pluginManager = manager;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
internal void DetachPluginManager()
|
||||
{
|
||||
pluginManager = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
|
||||
private void GetMMInterface()
|
||||
{
|
||||
mirandaMemoryManager = new MM_INTERFACE();
|
||||
mirandaMemoryManager.Size = Marshal.SizeOf(typeof(MM_INTERFACE));
|
||||
|
||||
UnmanagedStructHandle<MM_INTERFACE> mmiHandle = new UnmanagedStructHandle<MM_INTERFACE>(ref mirandaMemoryManager);
|
||||
|
||||
try
|
||||
{
|
||||
if (CallService(MS_SYSTEM_GET_MMI, IntPtr.Zero, mmiHandle.IntPtr) == CallbackResult.Success)
|
||||
mmiHandle.MarshalBack(out mirandaMemoryManager);
|
||||
else
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_SYSTEM_GET_MMI, "1"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
mmiHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
internal void PopulateContextInformation()
|
||||
{
|
||||
PopulateNetworkProtocols();
|
||||
}
|
||||
|
||||
private unsafe void PopulateNetworkProtocols()
|
||||
{
|
||||
try
|
||||
{
|
||||
int count;
|
||||
PROTOCOLDESCRIPTOR** pointerArrayPtr;
|
||||
|
||||
int result = CallServiceUnsafe(MirandaServices.MS_PROTO_ENUMPROTOCOLS, &count, &pointerArrayPtr);
|
||||
if (result != 0) throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MirandaServices.MS_PROTO_ENUMPROTOCOLS, result.ToString()));
|
||||
|
||||
ProtocolDictionary protocols = new ProtocolDictionary(count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// *(ptr_to_array_of_ptrs + i * sizeof(PROTOCOLDESCRIPTOR)) = *ptr_to_ptr = *ptr = data
|
||||
PROTOCOLDESCRIPTOR nativeDescriptor = **(((PROTOCOLDESCRIPTOR**)pointerArrayPtr) + i);
|
||||
Protocol protocol = new Protocol(ref nativeDescriptor);
|
||||
|
||||
protocols.Add(protocol.Name, protocol);
|
||||
}
|
||||
|
||||
this.protocols = protocols;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
this.protocols = new ProtocolDictionary(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateEnvironmentInformation()
|
||||
{
|
||||
InteropBuffer buffer = InteropBufferPool.AcquireBuffer();
|
||||
|
||||
try
|
||||
{
|
||||
buffer.Lock();
|
||||
|
||||
int result = CallService(MS_SYSTEM_GETVERSIONTEXT, buffer.SizeAsUIntPtr, buffer.IntPtr);
|
||||
Debug.Assert(result == 0);
|
||||
|
||||
if (result == 0 && Translate.ToString(buffer.IntPtr, StringEncoding.Ansi).IndexOf("Unicode") != -1)
|
||||
MirandaEnvironment.MirandaStringEncoding = StringEncoding.Unicode;
|
||||
else
|
||||
MirandaEnvironment.MirandaStringEncoding = StringEncoding.Ansi;
|
||||
}
|
||||
finally
|
||||
{
|
||||
buffer.Unlock();
|
||||
InteropBufferPool.ReleaseBuffer(buffer);
|
||||
}
|
||||
|
||||
MirandaEnvironment.MirandaVersion = Translate.FromMirandaVersion((uint)CallService(MirandaServices.MS_SYSTEM_GETVERSION));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
internal MirandaPluginLink PluginLink
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.pluginLink;
|
||||
}
|
||||
}
|
||||
|
||||
private MM_INTERFACE mirandaMemoryManager;
|
||||
internal MM_INTERFACE MirandaMemoryManager
|
||||
{
|
||||
get { return mirandaMemoryManager; }
|
||||
}
|
||||
|
||||
internal PluginManagerBase PluginManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.pluginManager == null)
|
||||
throw new InvalidOperationException("No plugin manager associated with this context.");
|
||||
|
||||
return this.pluginManager;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasPluginManager
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.pluginManager != null;
|
||||
}
|
||||
}
|
||||
|
||||
public static MirandaContext Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (singleton == null)
|
||||
throw new InvalidOperationException(TextResources.ExceptionMsg_MirandaContextNotAvailable);
|
||||
|
||||
return singleton;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Initialized
|
||||
{
|
||||
get
|
||||
{
|
||||
return singleton != null;
|
||||
}
|
||||
}
|
||||
|
||||
public ServiceCallInterceptionManager ServiceCallInterceptors
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.serviceInterceptors;
|
||||
}
|
||||
}
|
||||
|
||||
public MirandaDatabase MirandaDatabase
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.mirandaDatabase;
|
||||
}
|
||||
}
|
||||
|
||||
public ProtocolDictionary Protocols
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.protocols;
|
||||
}
|
||||
}
|
||||
|
||||
public ContactList ContactList
|
||||
{
|
||||
get { return contactList; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler ModulesLoaded;
|
||||
|
||||
internal void RaiseModulesLoadedEvent()
|
||||
{
|
||||
if (ModulesLoaded != null)
|
||||
ModulesLoaded(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
internal event EventHandler IsolatedModePluginsUnloading;
|
||||
|
||||
internal void RaiseIsolatedModePluginsUnloadingEvent()
|
||||
{
|
||||
if (IsolatedModePluginsUnloading != null)
|
||||
IsolatedModePluginsUnloading(null, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CallService
|
||||
|
||||
public int CallService(string serviceName)
|
||||
{
|
||||
return CallService(serviceName, UIntPtr.Zero, IntPtr.Zero, false);
|
||||
}
|
||||
|
||||
public int CallService(string serviceName, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return CallService(serviceName, Translate.ToHandle(wParam), lParam, false);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public int CallService(string serviceName, UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return CallService(serviceName, wParam, lParam, false);
|
||||
}
|
||||
|
||||
internal int CallService(string serviceName, UIntPtr wParam, IntPtr lParam, bool noInterception)
|
||||
{
|
||||
if (String.IsNullOrEmpty(serviceName))
|
||||
throw new ArgumentNullException("service");
|
||||
|
||||
int returnCode =
|
||||
serviceInterceptors.RequiresInterception(serviceName) && !noInterception ?
|
||||
serviceInterceptors[serviceName](wParam, lParam) : pluginLink.NativePluginLink.CallService(serviceName, wParam, lParam);
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
internal unsafe int CallServiceUnsafe(string serviceName, void* wParam, void* lParam)
|
||||
{
|
||||
return pluginLink.CallServiceUnsafe(serviceName, wParam, lParam);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,507 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using System.Threading;
|
||||
using System.Collections.ObjectModel;
|
||||
using Virtuoso.Hyphen;
|
||||
using Virtuoso.Miranda.Plugins.Helpers;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public sealed class MirandaDatabase : EventPublisher
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string ME_DB_EVENT_ADDED = "DB/Event/Added",
|
||||
ME_DB_EVENT_DELETED = "DB/Event/Deleted",
|
||||
ME_DB_EVENT_FILTER_ADD = "DB/Event/FilterAdd",
|
||||
ME_DB_CONTACT_ADDED = "DB/Contact/Added",
|
||||
ME_DB_CONTACT_DELETED = "DB/Contact/Deleted",
|
||||
ME_DB_CONTACT_SETTINGCHANGED = "DB/Contact/SettingChanged";
|
||||
|
||||
private const string MS_DB_GETPROFILENAME = "DB/GetProfileName",
|
||||
MS_DB_GETPROFILEPATH = "DB/GetProfilePath",
|
||||
MS_DB_EVENT_ADD = "DB/Event/Add";
|
||||
|
||||
private const string MS_DB_CONTACT_GETCOUNT = "DB/Contact/GetCount",
|
||||
MS_DB_CONTACT_FINDFIRST = "DB/Contact/FindFirst",
|
||||
MS_DB_CONTACT_FINDNEXT = "DB/Contact/FindNext";
|
||||
|
||||
private const string MS_DB_EVENT_FINDFIRST = "DB/Event/FindFirst",
|
||||
MS_DB_EVENT_FINDNEXT = "DB/Event/FindNext";
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
internal MirandaDatabase() { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private MirandaEventHandler<MirandaDatabaseEventArgs> EventAddedEventHandler,
|
||||
EventDeletedEventHandler, BeforeEventAddedEventHandler;
|
||||
|
||||
private MirandaEventHandler<MirandaContactEventArgs> ContactAddedEventHandler,
|
||||
ContactDeletedEventHandler;
|
||||
|
||||
private MirandaEventHandler<MirandaContactSettingEventArgs> ContactSettingChangedEventHandler;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events & Triggers
|
||||
|
||||
private int RaiseDbEvent(MirandaEventHandler<MirandaDatabaseEventArgs> handler, bool fromPointer, UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (handler == null)
|
||||
return 0;
|
||||
|
||||
ContactInfo contactInfo = ContactInfo.FromHandle(wParam);
|
||||
DatabaseEventInfo eventInfo = fromPointer ? DatabaseEventInfo.FromPointer(lParam) : DatabaseEventInfo.FromHandle(lParam);
|
||||
MirandaDatabaseEventArgs eventArgs = new MirandaDatabaseEventArgs(contactInfo, eventInfo);
|
||||
|
||||
bool retValue = InvokeChainCancelable<MirandaDatabaseEventArgs>(handler, eventArgs);
|
||||
return Convert.ToInt32(retValue);
|
||||
}
|
||||
|
||||
public event MirandaEventHandler<MirandaDatabaseEventArgs> EventAdded
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<MirandaEventHandler<MirandaDatabaseEventArgs>>(ref EventAddedEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_DB_EVENT_ADDED,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return RaiseDbEvent(EventAddedEventHandler, false, wParam, lParam);
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<MirandaEventHandler<MirandaDatabaseEventArgs>>(ref EventAddedEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_DB_EVENT_ADDED, EventAddedEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public event MirandaEventHandler<MirandaDatabaseEventArgs> EventDeleted
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<MirandaEventHandler<MirandaDatabaseEventArgs>>(ref EventDeletedEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_DB_EVENT_DELETED,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return RaiseDbEvent(EventDeletedEventHandler, false, wParam, lParam);
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<MirandaEventHandler<MirandaDatabaseEventArgs>>(ref EventDeletedEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_DB_EVENT_DELETED, EventDeletedEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return TRUE to filter out the event, FALSE to pass the message along.
|
||||
/// </summary>
|
||||
public event MirandaEventHandler<MirandaDatabaseEventArgs> BeforeEventAdded
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<MirandaEventHandler<MirandaDatabaseEventArgs>>(ref BeforeEventAddedEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_DB_EVENT_FILTER_ADD,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return RaiseDbEvent(BeforeEventAddedEventHandler, true, wParam, lParam);
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<MirandaEventHandler<MirandaDatabaseEventArgs>>(ref BeforeEventAddedEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_DB_EVENT_FILTER_ADD, BeforeEventAddedEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private int RaiseContactEvent(MirandaEventHandler<MirandaContactEventArgs> handler, UIntPtr wParam)
|
||||
{
|
||||
if (handler == null)
|
||||
return 0;
|
||||
|
||||
ContactInfo contactInfo = GetContactInfo(wParam);
|
||||
MirandaContactEventArgs eventArgs = new MirandaContactEventArgs(contactInfo);
|
||||
|
||||
bool retValue = InvokeChainCancelable<MirandaContactEventArgs>(handler, eventArgs);
|
||||
return Convert.ToInt32(retValue);
|
||||
}
|
||||
|
||||
private static ContactInfo GetContactInfo(UIntPtr wParam)
|
||||
{
|
||||
if (wParam == UIntPtr.Zero)
|
||||
return ContactInfo.MeNeutral;
|
||||
else
|
||||
return ContactInfo.FromHandle(wParam);
|
||||
}
|
||||
|
||||
private unsafe int RaiseContactSettingEvent(UIntPtr hContact, IntPtr pDbWriteSetting)
|
||||
{
|
||||
DBCONTACTWRITESETTING dbWriteSetting = *(DBCONTACTWRITESETTING*)pDbWriteSetting.ToPointer();
|
||||
ContactInfo contactInfo = GetContactInfo(hContact);
|
||||
|
||||
string name = Translate.ToString(dbWriteSetting.Name, StringEncoding.Ansi);
|
||||
string moduleName = Translate.ToString(dbWriteSetting.Module, StringEncoding.Ansi);
|
||||
object value = null;
|
||||
|
||||
if ((DatabaseSettingType)dbWriteSetting.Value.Type != DatabaseSettingType.Blob)
|
||||
value = DBCONTACTWRITESETTING.ExtractValue(pDbWriteSetting);
|
||||
else
|
||||
Debugger.Log(10, Loader.LogCategory, "Blob settings are not yet supported, the value will be null.");
|
||||
|
||||
MirandaContactSettingEventArgs eventArgs = new MirandaContactSettingEventArgs(contactInfo, name, moduleName, value, (DatabaseSettingType)dbWriteSetting.Value.Type);
|
||||
|
||||
bool retValue = InvokeChainCancelable<MirandaContactSettingEventArgs>(ContactSettingChangedEventHandler, eventArgs);
|
||||
return Convert.ToInt32(retValue);
|
||||
}
|
||||
|
||||
public event MirandaEventHandler<MirandaContactEventArgs> ContactAdded
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<MirandaEventHandler<MirandaContactEventArgs>>(ref ContactAddedEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_DB_CONTACT_ADDED,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return RaiseContactEvent(ContactAddedEventHandler, wParam);
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<MirandaEventHandler<MirandaContactEventArgs>>(ref ContactAddedEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_DB_CONTACT_ADDED, ContactAddedEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public event MirandaEventHandler<MirandaContactEventArgs> ContactDeleted
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<MirandaEventHandler<MirandaContactEventArgs>>(ref ContactDeletedEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_DB_CONTACT_DELETED,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return RaiseContactEvent(ContactDeletedEventHandler, wParam);
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<MirandaEventHandler<MirandaContactEventArgs>>(ref ContactDeletedEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_DB_CONTACT_DELETED, ContactDeletedEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public event MirandaEventHandler<MirandaContactSettingEventArgs> ContactSettingChanged
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<MirandaEventHandler<MirandaContactSettingEventArgs>>(ref ContactSettingChangedEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_DB_CONTACT_SETTINGCHANGED,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return RaiseContactSettingEvent(wParam, lParam);
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<MirandaEventHandler<MirandaContactSettingEventArgs>>(ref ContactSettingChangedEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChangedEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
#region Profile
|
||||
|
||||
public string ProfileName
|
||||
{
|
||||
get
|
||||
{
|
||||
InteropBuffer buffer = InteropBufferPool.AcquireBuffer();
|
||||
|
||||
try
|
||||
{
|
||||
buffer.Lock();
|
||||
|
||||
int result = MirandaContext.Current.CallService(MS_DB_GETPROFILENAME, buffer.SizeAsUIntPtr, buffer.IntPtr);
|
||||
Debug.Assert(result == 0);
|
||||
|
||||
if (result != 0) return null;
|
||||
return Translate.ToString(buffer.IntPtr, StringEncoding.Ansi);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new MirandaException(TextResources.ExceptionMsg_ErrorWhileCallingMirandaService, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
buffer.Unlock();
|
||||
InteropBufferPool.ReleaseBuffer(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string ProfilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
InteropBuffer buffer = InteropBufferPool.AcquireBuffer();
|
||||
|
||||
try
|
||||
{
|
||||
buffer.Lock();
|
||||
|
||||
int result = MirandaContext.Current.CallService(MS_DB_GETPROFILEPATH, buffer.SizeAsUIntPtr, buffer.IntPtr);
|
||||
Debug.Assert(result == 0);
|
||||
|
||||
if (result != 0) return null;
|
||||
return Translate.ToString(buffer.IntPtr, StringEncoding.Ansi);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new MirandaException(TextResources.ExceptionMsg_ErrorWhileCallingMirandaService, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
buffer.Unlock();
|
||||
InteropBufferPool.ReleaseBuffer(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
#region Contacts
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates contact handles, excluding the Me contact.
|
||||
/// </summary>
|
||||
/// <returns>Contact handles.</returns>
|
||||
public IEnumerable<IntPtr> GetContactHandles()
|
||||
{
|
||||
MirandaContext context = MirandaContext.Current;
|
||||
Callback findNext = ServiceManager.GetService(MS_DB_CONTACT_FINDNEXT);
|
||||
|
||||
UIntPtr handle = (UIntPtr)(uint)context.CallService(MS_DB_CONTACT_FINDFIRST);
|
||||
|
||||
do
|
||||
{
|
||||
if (handle != UIntPtr.Zero)
|
||||
yield return Translate.ToHandle(handle);
|
||||
}
|
||||
while ((handle = (UIntPtr)(uint)findNext(handle, IntPtr.Zero)) != UIntPtr.Zero);
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<ContactInfo> GetContacts()
|
||||
{
|
||||
return GetContacts(false);
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<ContactInfo> GetContacts(bool includeSelf)
|
||||
{
|
||||
MirandaContext context = MirandaContext.Current;
|
||||
Callback findNext = ServiceManager.GetService(MS_DB_CONTACT_FINDNEXT);
|
||||
|
||||
List<ContactInfo> contacts = new List<ContactInfo>(context.CallService(MS_DB_CONTACT_GETCOUNT));
|
||||
|
||||
if (includeSelf)
|
||||
contacts.Add(ContactInfo.MeNeutral);
|
||||
|
||||
foreach (IntPtr handle in GetContactHandles())
|
||||
contacts.Add(ContactInfo.FromHandle(handle));
|
||||
|
||||
return contacts.AsReadOnly();
|
||||
}
|
||||
|
||||
public ContactInfo FindContact(string uuid)
|
||||
{
|
||||
return FindContact(uuid, ContactInfoProperty.UniqueID, StringEncoding.Ansi);
|
||||
}
|
||||
|
||||
public ContactInfo FindContact(string searchValue, ContactInfoProperty searchCriterion, StringEncoding valueEncoding)
|
||||
{
|
||||
return FindContact(searchValue, searchCriterion, valueEncoding, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public ContactInfo FindContact(string searchValue, ContactInfoProperty searchCriterion, StringEncoding valueEncoding, StringComparison comparisonType)
|
||||
{
|
||||
if (searchValue == null)
|
||||
throw new ArgumentNullException("searchValues");
|
||||
|
||||
foreach (IntPtr handle in GetContactHandles())
|
||||
{
|
||||
object value;
|
||||
ContactInfoPropertyType type;
|
||||
|
||||
if (ContactInfo.GetProperty(handle, searchCriterion, out value, out type)
|
||||
&& searchValue.Equals(value.ToString(), comparisonType))
|
||||
return ContactInfo.FromHandle(handle);
|
||||
}
|
||||
|
||||
Debug.Assert(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
public ContactInfo[] FindContacts(params string[] uuids)
|
||||
{
|
||||
if (uuids == null)
|
||||
throw new ArgumentNullException("uuids");
|
||||
|
||||
List<ContactInfo> results = new List<ContactInfo>(uuids.Length);
|
||||
|
||||
foreach (string uuid in uuids)
|
||||
{
|
||||
ContactInfo contact = FindContact(uuid, ContactInfoProperty.UniqueID, StringEncoding.Ansi);
|
||||
|
||||
if (contact != null)
|
||||
results.Add(contact);
|
||||
}
|
||||
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public IntPtr AddEvent(ContactInfo associatedContact, object data, ISettingOwner owner, DatabaseEventType type, DatabaseEventProperties flags, DateTime? timestamp)
|
||||
{
|
||||
return AddEvent(associatedContact, data, owner, type, flags, timestamp, true);
|
||||
}
|
||||
|
||||
public IntPtr AddEvent(ContactInfo associatedContact, object data, ISettingOwner owner, DatabaseEventType type, DatabaseEventProperties flags, DateTime? timestamp, bool throwOnFailure)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
return AddEvent(associatedContact, data, owner.Name, type, flags, timestamp, throwOnFailure);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IntPtr> GetEventHandles(ContactInfo owner)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
return GetEventHandles(owner.MirandaHandle);
|
||||
}
|
||||
|
||||
public IEnumerable<IntPtr> GetEventHandles(IntPtr ownerHandle)
|
||||
{
|
||||
Callback findNext = ServiceManager.GetService(MS_DB_EVENT_FINDNEXT);
|
||||
IntPtr pEvent = (IntPtr)MirandaContext.Current.CallService(MS_DB_EVENT_FINDFIRST, ownerHandle, IntPtr.Zero);
|
||||
|
||||
while (pEvent != IntPtr.Zero)
|
||||
{
|
||||
yield return pEvent;
|
||||
pEvent = (IntPtr)findNext(Translate.ToHandle(pEvent), IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[Serializable]
|
||||
public class MirandaDatabaseEventArgs : MirandaContactEventArgs
|
||||
{
|
||||
#region .ctors
|
||||
|
||||
public MirandaDatabaseEventArgs(ContactInfo contact, DatabaseEventInfo eventInfo) : base(contact)
|
||||
{
|
||||
if (eventInfo == null)
|
||||
throw new ArgumentNullException("eventInfo");
|
||||
|
||||
this.eventInfo = eventInfo;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private readonly DatabaseEventInfo eventInfo;
|
||||
public DatabaseEventInfo EventInfo
|
||||
{
|
||||
get { return eventInfo; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.IO;
|
||||
using Virtuoso.Hyphen;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public static class MirandaEnvironment
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static Version mirandaVersion;
|
||||
private static StringEncoding mirandaStringEncoding;
|
||||
|
||||
internal const string MirandaPluginsFolderRelativePath = @"plugins\",
|
||||
ManagedPluginsFolderName = "managed",
|
||||
ManagedPluginsFolderRelativePath = MirandaPluginsFolderRelativePath + ManagedPluginsFolderName;
|
||||
|
||||
private static readonly string mirandaFolderPath = Application.StartupPath,
|
||||
mirandaPluginsFolderPath = Path.Combine(mirandaFolderPath, MirandaPluginsFolderRelativePath),
|
||||
managedPluginsFolderPath = Path.Combine(mirandaFolderPath, ManagedPluginsFolderRelativePath),
|
||||
mirandaBootIniPath = mirandaFolderPath + @"\MirandaBoot.ini";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public static string GetManagedSubdirectoryRelativePath(string subDir)
|
||||
{
|
||||
return Path.Combine(ManagedPluginsFolderRelativePath, subDir);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public static StringEncoding MirandaStringEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
return mirandaStringEncoding;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
mirandaStringEncoding = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static string MirandaFolderPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return mirandaFolderPath;
|
||||
}
|
||||
}
|
||||
|
||||
public static string MirandaPluginsFolderPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return mirandaPluginsFolderPath;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ManagedPluginsFolderPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return managedPluginsFolderPath;
|
||||
}
|
||||
}
|
||||
|
||||
public static Version MirandaVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return mirandaVersion;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
mirandaVersion = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static Version HyphenVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return Loader.HyphenVersion;
|
||||
}
|
||||
}
|
||||
|
||||
public static string MirandaBootIniPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return mirandaBootIniPath;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[Serializable]
|
||||
public abstract class MirandaEventArgs : EventArgs
|
||||
{
|
||||
protected MirandaEventArgs() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic handler for Miranda-raised events.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEventArgs">Type of EventArgs.</typeparam>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
/// <param name="e">Event arguments.</param>
|
||||
/// <returns>TRUE to block the event from bubbling to another subscribers, FALSE to pass it along.</returns>
|
||||
public delegate bool MirandaEventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs : MirandaEventArgs;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
internal static class MirandaEvents
|
||||
{
|
||||
public const string ME_SYSTEM_SHUTDOWN = "Miranda/System/Shutdown",
|
||||
ME_SYSTEM_OKTOEXIT = "Miranda/System/OkToExitEvent",
|
||||
ME_DB_EVENT_ADDED = "DB/Event/Added",
|
||||
ME_DB_EVENT_DELETED = "DB/Event/Deleted",
|
||||
ME_DB_CONTACT_ADDED = "DB/Contact/Added",
|
||||
ME_DB_CONTACT_DELETED = "DB/Contact/Deleted",
|
||||
ME_DB_CONTACT_SETTINGCHANGED = "DB/Contact/SettingChanged",
|
||||
ME_SYSTEM_MODULESLOADED = "Miranda/System/ModulesLoaded";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public enum ItemType : int
|
||||
{
|
||||
Unspecified,
|
||||
Contact,
|
||||
Group
|
||||
}
|
||||
|
||||
public class MirandaItem : MirandaObject
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static readonly Type ItemTypeType = typeof(ItemType);
|
||||
|
||||
private ItemType type;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
protected MirandaItem(IntPtr handle, ItemType type) : this(handle)
|
||||
{
|
||||
if (!Enum.IsDefined(ItemTypeType, type))
|
||||
throw new ArgumentOutOfRangeException("type");
|
||||
|
||||
if (type == ItemType.Unspecified)
|
||||
throw new ArgumentException("Unspecified type is not supported.");
|
||||
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
internal MirandaItem(IntPtr handle)
|
||||
{
|
||||
this.MirandaHandle = handle;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public ItemType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public abstract class MirandaObject : IMirandaObject
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private IntPtr mirandaHandle;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
protected MirandaObject() { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public IntPtr MirandaHandle
|
||||
{
|
||||
get { return mirandaHandle; }
|
||||
protected internal set { mirandaHandle = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
internal static class MirandaServices
|
||||
{
|
||||
public const string MS_CLIST_ADDMAINMENUITEM = "CList/AddMainMenuItem",
|
||||
MS_CLIST_ADDCONTACTMENUITEM = "CList/AddContactMenuItem",
|
||||
MS_CLIST_MODIFYMENUITEM = "CList/ModifyMenuItem",
|
||||
MS_CLIST_SYSTRAY_NOTIFY = "Miranda/Systray/Notify",
|
||||
MS_CONTACT_GETCONTACTINFO = "Miranda/Contact/GetContactInfo",
|
||||
|
||||
MS_PROTO_GETCONTACTBASEPROTO = "Proto/GetContactBaseProto",
|
||||
MS_PROTO_ENUMPROTOCOLS = "Proto/EnumProtocols",
|
||||
MS_PROTO_CALLCONTACTSERVICE = "Proto/CallContactService",
|
||||
MS_PROTO_REGISTERMODULE = "Proto/RegisterModule",
|
||||
PS_MESSAGE = "/SendMsg",
|
||||
MS_SYSTEM_GETVERSION = "Miranda/System/GetVersion";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.IsolatedStorage;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using Virtuoso.Miranda.Plugins.Collections;
|
||||
using Virtuoso.Miranda.Plugins.Configuration;
|
||||
using Virtuoso.Miranda.Plugins.Helpers;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[Serializable]
|
||||
public abstract class PluginConfiguration
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static readonly object SyncObject = new object();
|
||||
|
||||
private static readonly TypeInstanceCache<IStorage> Stores = new TypeInstanceCache<IStorage>();
|
||||
private static readonly TypeInstanceCache<IEncryption> Encryptions = new TypeInstanceCache<IEncryption>();
|
||||
|
||||
internal readonly ConfigurationValues values;
|
||||
|
||||
private bool isDirty;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
protected PluginConfiguration()
|
||||
{
|
||||
values = new ConfigurationValues();
|
||||
}
|
||||
|
||||
protected virtual void InitializeDefaultConfiguration() { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
[field: NonSerialized]
|
||||
public event EventHandler ConfigurationChanged;
|
||||
|
||||
protected void RaiseChangedEvent()
|
||||
{
|
||||
if (ConfigurationChanged != null)
|
||||
ConfigurationChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public ConfigurationValues Values
|
||||
{
|
||||
get
|
||||
{
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDirty
|
||||
{
|
||||
get
|
||||
{
|
||||
return isDirty;
|
||||
}
|
||||
protected internal set
|
||||
{
|
||||
isDirty = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected virtual void OnBeforeSerialization() { }
|
||||
|
||||
protected virtual void OnAfterDeserialization() { }
|
||||
|
||||
protected void MarkDirty()
|
||||
{
|
||||
IsDirty = true;
|
||||
RaiseChangedEvent();
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
private static ConfigurationOptionsAttribute GetOptions(Type configType)
|
||||
{
|
||||
if (configType == null)
|
||||
throw new ArgumentNullException("configType");
|
||||
|
||||
ConfigurationOptionsAttribute options = null;
|
||||
Type configAttribType = typeof(ConfigurationOptionsAttribute);
|
||||
|
||||
if (configType.IsDefined(configAttribType, false))
|
||||
options = (ConfigurationOptionsAttribute)configType.GetCustomAttributes(configAttribType, false)[0];
|
||||
else
|
||||
options = new ConfigurationOptionsAttribute();
|
||||
|
||||
return options.Finalize();
|
||||
}
|
||||
|
||||
private static byte[] FetchStream(Stream stream)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException("stream");
|
||||
|
||||
if (!stream.CanRead)
|
||||
throw new ArgumentException();
|
||||
|
||||
byte[] buffer = new byte[stream.Length];
|
||||
|
||||
if (stream.Read(buffer, 0, buffer.Length) != stream.Length)
|
||||
throw new IOException();
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
internal static void FlushCaches()
|
||||
{
|
||||
lock (SyncObject)
|
||||
{
|
||||
foreach (IStorage storage in Stores.Values)
|
||||
storage.Dispose();
|
||||
|
||||
Stores.Clear();
|
||||
Encryptions.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Save
|
||||
|
||||
public void Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObject)
|
||||
{
|
||||
OnBeforeSerialization();
|
||||
|
||||
ConfigurationOptionsAttribute options = GetOptions(GetType());
|
||||
IStorage storage = Stores.Instantiate(options.Storage);
|
||||
|
||||
if (options.Encrypt)
|
||||
SerializeEncrypted(storage, options);
|
||||
else
|
||||
Serialize(storage, options);
|
||||
}
|
||||
}
|
||||
catch (IsolatedStorageException isE)
|
||||
{
|
||||
throw new ConfigurationException(TextResources.ExceptionMsg_UnableToSaveConfiguration_StorageError, isE);
|
||||
}
|
||||
}
|
||||
|
||||
private void Serialize(IStorage storage, ConfigurationOptionsAttribute options)
|
||||
{
|
||||
BinaryFormatter serializer = new BinaryFormatter();
|
||||
|
||||
using (Stream stream = storage.OpenWrite(GetType(), options))
|
||||
serializer.Serialize(stream, this);
|
||||
}
|
||||
|
||||
private void SerializeEncrypted(IStorage storage, ConfigurationOptionsAttribute options)
|
||||
{
|
||||
IEncryption encryption = Encryptions.Instantiate(options.Encryption);
|
||||
|
||||
using (Stream serializationStream = new MemoryStream(2048))
|
||||
{
|
||||
new BinaryFormatter().Serialize(serializationStream, this);
|
||||
serializationStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
byte[] data = FetchStream(serializationStream);
|
||||
byte[] protectedData = encryption.Encrypt(data);
|
||||
|
||||
using (Stream stream = storage.OpenWrite(GetType(), options))
|
||||
stream.Write(protectedData, 0, protectedData.Length);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Load
|
||||
|
||||
public static T Load<T>() where T : PluginConfiguration
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObject)
|
||||
{
|
||||
Type configType = typeof(T);
|
||||
ConfigurationOptionsAttribute options = GetOptions(configType);
|
||||
|
||||
IStorage storage = Stores.Instantiate(options.Storage);
|
||||
|
||||
if (!storage.Exists(configType, options))
|
||||
return GetDefaultConfiguration<T>();
|
||||
|
||||
using (Stream stream = storage.OpenRead(configType, options))
|
||||
{
|
||||
T result = null;
|
||||
|
||||
if (options.Encrypt)
|
||||
result = DeserializeEncrypted<T>(stream, options);
|
||||
else
|
||||
result = Deserialize<T>(stream);
|
||||
|
||||
result.OnAfterDeserialization();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException e)
|
||||
{
|
||||
throw new ConfigurationException(TextResources.ExceptionMsg_UnableToLoadConfiguration_StorageError, e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
T defaults = GetDefaultConfiguration<T>();
|
||||
defaults.Save();
|
||||
|
||||
throw new ConfigurationException(TextResources.ExceptionMsg_UnableToLoadConfiguration_StorageError, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static T Deserialize<T>(Stream stream) where T : PluginConfiguration
|
||||
{
|
||||
return new BinaryFormatter().Deserialize(stream) as T;
|
||||
}
|
||||
|
||||
private static T DeserializeEncrypted<T>(Stream stream, ConfigurationOptionsAttribute options) where T : PluginConfiguration
|
||||
{
|
||||
byte[] protectedData = FetchStream(stream);
|
||||
byte[] data = Encryptions.Instantiate(options.Encryption).Decrypt(protectedData);
|
||||
|
||||
using (Stream serializedStream = new MemoryStream(data))
|
||||
return new BinaryFormatter().Deserialize(serializedStream) as T;
|
||||
}
|
||||
|
||||
public static TConfig GetDefaultConfiguration<TConfig>() where TConfig : PluginConfiguration
|
||||
{
|
||||
TConfig result = Activator.CreateInstance(typeof(TConfig), true) as TConfig;
|
||||
|
||||
if (result == null)
|
||||
throw new ConfigurationException();
|
||||
|
||||
result.InitializeDefaultConfiguration();
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Runtime.InteropServices;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using Virtuoso.Hyphen;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Virtuoso.Miranda.Plugins.Infrastructure.Protocols;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public class Protocol : ContextWorker, ISettingOwner
|
||||
{
|
||||
#region Constants
|
||||
|
||||
internal const string PS_GETSTATUS = "/GetStatus";
|
||||
internal const string PS_SETSTATUS = "/SetStatus";
|
||||
internal const string PS_GETCAPS = "/GetCaps";
|
||||
internal const string PS_GETNAME = "/GetName";
|
||||
internal const string PS_LOADICON = "/LoadIcon";
|
||||
internal const string PSS_MESSAGE = "/SendMsg";
|
||||
|
||||
private const string MS_PROTO_ISPROTOONCONTACT = "Proto/IsProtoOnContact";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
private static readonly Protocol unknownProtocol = new Protocol();
|
||||
|
||||
private readonly string name;
|
||||
private readonly ProtocolType type;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
internal Protocol()
|
||||
{
|
||||
this.name = String.Empty;
|
||||
this.type = ProtocolType.Other;
|
||||
}
|
||||
|
||||
internal Protocol(string name, ProtocolType type)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name))
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
if (!Enum.IsDefined(typeof(ProtocolType), type))
|
||||
throw new ArgumentOutOfRangeException("type");
|
||||
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
internal Protocol(ref PROTOCOLDESCRIPTOR descriptor)
|
||||
{
|
||||
if (descriptor.Name == IntPtr.Zero)
|
||||
throw new ArgumentException();
|
||||
|
||||
this.name = Translate.ToString(descriptor.Name, StringEncoding.Ansi);
|
||||
this.type = (ProtocolType)descriptor.Type;
|
||||
}
|
||||
|
||||
~Protocol()
|
||||
{
|
||||
if (namePtr.IsValid)
|
||||
namePtr.Free();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
private static MirandaEventHandler<ProtocolStatusChangeEventArgs> StatusChangedEventHandler;
|
||||
public static event MirandaEventHandler<ProtocolStatusChangeEventArgs> StatusChanged
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
// Important to check to not hook the Ack for nothing
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
// First subscriber?
|
||||
if (StatusChangedEventHandler == null)
|
||||
AckRouter.AckReceived += AckRouter_AckReceived;
|
||||
|
||||
LazyEventBinder.AttachDelegate<MirandaEventHandler<ProtocolStatusChangeEventArgs>>(ref StatusChangedEventHandler, value);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<MirandaEventHandler<ProtocolStatusChangeEventArgs>>(ref StatusChangedEventHandler, value);
|
||||
|
||||
// No more subscribers?
|
||||
if (StatusChangedEventHandler == null)
|
||||
AckRouter.AckReceived -= AckRouter_AckReceived;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool AckRouter_AckReceived(object sender, AckEventArgs e)
|
||||
{
|
||||
if (e.Type == AckType.Status)
|
||||
{
|
||||
if (StatusChangedEventHandler != null)
|
||||
StatusChangedEventHandler(e.Protocol, new ProtocolStatusChangeEventArgs(e.Protocol, (StatusMode)e.LParam));
|
||||
}
|
||||
|
||||
return EventResult.HonourEventChain;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private void CheckUnknown()
|
||||
{
|
||||
if (String.IsNullOrEmpty(name))
|
||||
throw new InvalidOperationException(TextResources.ExceptionMsg_CallInvalidForUnknownNetworkProtocol);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public int CallProtocolService(string serviceName, UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (serviceName == null)
|
||||
throw new ArgumentNullException("serviceName");
|
||||
|
||||
CheckUnknown();
|
||||
return MirandaContext.Current.CallService(GetProtoServiceName(serviceName), wParam, lParam);
|
||||
}
|
||||
|
||||
public string GetProtoServiceName(string service)
|
||||
{
|
||||
if (service == null)
|
||||
throw new ArgumentNullException("service");
|
||||
|
||||
return String.Format("{0}{1}", Name, service);
|
||||
}
|
||||
|
||||
public bool HasInChain(ContactInfo contact)
|
||||
{
|
||||
if (contact == null)
|
||||
throw new ArgumentNullException("contact");
|
||||
|
||||
return HasInChain(contact.MirandaHandle);
|
||||
}
|
||||
|
||||
public bool HasInChain(IntPtr contactHandle)
|
||||
{
|
||||
return Convert.ToBoolean(Context.CallService(MS_PROTO_ISPROTOONCONTACT, contactHandle, NamePtr));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public static Protocol UnknownProtocol
|
||||
{
|
||||
get { return Protocol.unknownProtocol; }
|
||||
}
|
||||
|
||||
public StatusMode Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return (StatusMode)CallProtocolService(PS_GETSTATUS, UIntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
set
|
||||
{
|
||||
CallProtocolService(PS_SETSTATUS, (UIntPtr)value, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
public ProtocolType Type
|
||||
{
|
||||
get { return type; }
|
||||
}
|
||||
|
||||
public bool IsUnknown
|
||||
{
|
||||
get
|
||||
{
|
||||
return object.ReferenceEquals(this, UnknownProtocol);
|
||||
}
|
||||
}
|
||||
|
||||
private UnmanagedStringHandle namePtr;
|
||||
protected virtual IntPtr NamePtr
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!namePtr.IsValid)
|
||||
namePtr = Translate.ToHandle(Name, StringEncoding.Ansi);
|
||||
|
||||
return namePtr.IntPtr;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public static class ProtocolStatus
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private const string MS_AWAYMSG_SHOWAWAYMSG = "SRAway/GetMessage",
|
||||
MS_AWAYMSG_GETSTATUSMSG = "SRAway/GetStatusMessage";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public static bool ShowAwayMessage(ContactInfo contact)
|
||||
{
|
||||
int result = MirandaContext.Current.CallService(MS_AWAYMSG_SHOWAWAYMSG, contact.MirandaHandle, IntPtr.Zero);
|
||||
Debug.Assert(result == 0);
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
public static string GetStatusMessage(StatusMode status)
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(StatusMode), status))
|
||||
throw new ArgumentOutOfRangeException("status");
|
||||
|
||||
IntPtr statusPtr = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
statusPtr = (IntPtr)MirandaContext.Current.CallService(MS_AWAYMSG_GETSTATUSMSG, (UIntPtr)(ulong)status, IntPtr.Zero);
|
||||
if (statusPtr == IntPtr.Zero) return null;
|
||||
|
||||
return Translate.ToString(statusPtr, Virtuoso.Miranda.Plugins.Native.StringEncoding.Ansi);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_AWAYMSG_GETSTATUSMSG, 0), e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (statusPtr != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(statusPtr);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public class ProtocolStatusChangeEventArgs : MirandaEventArgs
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private StatusMode newStatus;
|
||||
public StatusMode NewStatus
|
||||
{
|
||||
get { return newStatus; }
|
||||
}
|
||||
|
||||
private Protocol protocol;
|
||||
public Protocol Protocol
|
||||
{
|
||||
get { return protocol; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
public ProtocolStatusChangeEventArgs(Protocol protocol, StatusMode newStatus)
|
||||
{
|
||||
this.newStatus = newStatus;
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using System.Threading;
|
||||
using System.Security;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure.Protocols
|
||||
{
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static class AckBroadcaster
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string MS_PROTO_BROADCASTACK = "Proto/BroadcastAck";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
private static ACKDATA BuildAckData(IntPtr pModuleName, AckType type, bool success, IntPtr contactHandle, IntPtr processHandle, IntPtr lParam)
|
||||
{
|
||||
ACKDATA ack = new ACKDATA(pModuleName, (int)type, success ? (int)AckResult.Success : (int)AckResult.Failure);
|
||||
ack.ContactHandle = contactHandle;
|
||||
ack.ProcessHandle = processHandle;
|
||||
ack.LParam = lParam;
|
||||
|
||||
return ack;
|
||||
}
|
||||
|
||||
private static unsafe int BroadcastAck(ACKDATA* ack)
|
||||
{
|
||||
return MirandaContext.Current.CallServiceUnsafe(MS_PROTO_BROADCASTACK, null, ack);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public static int BroadcastAck(string moduleName, AckType type, bool success, IntPtr contactHandle, IntPtr processHandle, IntPtr lParam)
|
||||
{
|
||||
UnmanagedStringHandle pModuleName = UnmanagedStringHandle.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
pModuleName = new UnmanagedStringHandle(moduleName, StringEncoding.Ansi);
|
||||
return BroadcastAck(pModuleName.IntPtr, type, success, contactHandle, processHandle, lParam);
|
||||
}
|
||||
finally
|
||||
{
|
||||
pModuleName.Free();
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe void BroadcastMessageAckAsync(IntPtr pModuleName, bool success, IntPtr contactHandle, int processCookie)
|
||||
{
|
||||
ACKDATA ack = BuildAckData(pModuleName, AckType.Message, success, contactHandle, (IntPtr)processCookie, IntPtr.Zero);
|
||||
ThreadPool.QueueUserWorkItem(delegate(object ackObject)
|
||||
{
|
||||
ACKDATA _ack = (ACKDATA)ackObject;
|
||||
BroadcastAck(&_ack);
|
||||
}, ack);
|
||||
}
|
||||
|
||||
public static unsafe int BroadcastAck(IntPtr pModuleName, AckType type, bool success, IntPtr contactHandle, IntPtr processHandle, IntPtr lParam)
|
||||
{
|
||||
ACKDATA ack = BuildAckData(pModuleName, type, success, contactHandle, processHandle, lParam);
|
||||
return BroadcastAck(&ack);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure.Protocols
|
||||
{
|
||||
public enum AckType : int
|
||||
{
|
||||
Message = 0,
|
||||
Url = 1,
|
||||
File = 2,
|
||||
Chat = 3,
|
||||
AwayMessage = 4,
|
||||
AuthorizationRequest = 5,
|
||||
Added = 6,
|
||||
GetInfo = 7,
|
||||
SetInfo = 8,
|
||||
Login = 9,
|
||||
Search = 10,
|
||||
NewUser = 11,
|
||||
Status = 12,
|
||||
Contacts = 13, //send/recv of contacts
|
||||
Avatar = 14, //send/recv of avatars from a protocol
|
||||
}
|
||||
|
||||
public enum AckResult : int
|
||||
{
|
||||
Success = 0,
|
||||
Failure = 1,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure.Protocols
|
||||
{
|
||||
public sealed class AckEventArgs : MirandaEventArgs
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private Protocol protocol;
|
||||
public Protocol Protocol
|
||||
{
|
||||
get { return protocol; }
|
||||
}
|
||||
|
||||
private ContactInfo contact;
|
||||
public ContactInfo Contact
|
||||
{
|
||||
get { return contact; }
|
||||
}
|
||||
|
||||
private AckType type;
|
||||
public AckType Type
|
||||
{
|
||||
get { return type; }
|
||||
}
|
||||
|
||||
private AckResult result;
|
||||
public AckResult Result
|
||||
{
|
||||
get { return result; }
|
||||
}
|
||||
|
||||
private IntPtr processHandle;
|
||||
public IntPtr ProcessHandle
|
||||
{
|
||||
get { return processHandle; }
|
||||
}
|
||||
|
||||
private IntPtr lParam;
|
||||
public IntPtr LParam
|
||||
{
|
||||
get { return lParam; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
public AckEventArgs() { }
|
||||
|
||||
internal unsafe static AckEventArgs FromACKDATA(IntPtr pAckData)
|
||||
{
|
||||
if (pAckData == IntPtr.Zero)
|
||||
throw new ArgumentNullException("pAckData");
|
||||
|
||||
ACKDATA ackData = *(ACKDATA*)pAckData.ToPointer();
|
||||
AckEventArgs ackArgs = new AckEventArgs();
|
||||
|
||||
ackArgs.contact = ContactInfo.FromHandle(ackData.ContactHandle);
|
||||
ackArgs.lParam = ackData.LParam;
|
||||
ackArgs.processHandle = ackData.ProcessHandle;
|
||||
ackArgs.result = (AckResult)ackData.Result;
|
||||
ackArgs.type = (AckType)ackData.Type;
|
||||
|
||||
if (ackData.ModuleName != IntPtr.Zero)
|
||||
ackArgs.protocol = MirandaContext.Current.Protocols[Translate.ToString(ackData.ModuleName, StringEncoding.Ansi)];
|
||||
|
||||
return ackArgs;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure.Protocols
|
||||
{
|
||||
public static class AckRouter
|
||||
{
|
||||
#region Constants
|
||||
|
||||
/// <summary>
|
||||
/// Call the next service in the chain for this send operation.
|
||||
/// wParam=wParam
|
||||
/// lParam=lParam
|
||||
/// The return value should be returned immediately
|
||||
/// wParam and lParam should be passed as the parameters that your service was
|
||||
/// called with. wParam must remain untouched but lParam is a CCSDATA structure
|
||||
/// that can be copied and modified if needed.
|
||||
/// Typically, the last line of any chaining protocol function is
|
||||
/// return CallService(MS_PROTO_CHAINSEND,wParam,lParam);
|
||||
/// </summary>
|
||||
private const string MS_PROTO_CHAINSEND = "Proto/ChainSend";
|
||||
|
||||
/// <summary>
|
||||
/// Call the next service in the chain for this receive operation
|
||||
/// wParam=wParam
|
||||
/// lParam=lParam
|
||||
/// The return value should be returned immediately
|
||||
/// wParam and lParam should be passed as the parameters that your service was
|
||||
/// called with. wParam must remain untouched but lParam is a CCSDATA structure
|
||||
/// that can be copied and modified if needed.
|
||||
/// When being initiated by the network-access protocol module, wParam should be
|
||||
/// zero.
|
||||
/// Thread safety: ms_proto_chainrecv is completely thread safe since 0.1.2.0
|
||||
/// Calls to it are translated to the main thread and passed on from there. The
|
||||
/// function will not return until all callees have returned, irrepective of
|
||||
/// differences between threads the functions are in.
|
||||
/// </summary>
|
||||
private const string MS_PROTO_CHAINRECV = "Proto/ChainRecv";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
private const string ME_PROTO_ACK = "Proto/Ack";
|
||||
private static MirandaEventHandler<AckEventArgs> AckReceivedEventHandler;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public static event MirandaEventHandler<AckEventArgs> AckReceived
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
add
|
||||
{
|
||||
LazyEventBinder.AttachDelegate<MirandaEventHandler<AckEventArgs>>(ref AckReceivedEventHandler, value);
|
||||
LazyEventBinder.HookMirandaEvent(ME_PROTO_ACK,
|
||||
delegate(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
AckEventArgs e = AckEventArgs.FromACKDATA(lParam);
|
||||
|
||||
EventPublisher.InvokeChainCancelable<AckEventArgs>(AckReceivedEventHandler, null, e);
|
||||
return (int)CallbackResult.Success;
|
||||
});
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
remove
|
||||
{
|
||||
LazyEventBinder.DetachDelegate<MirandaEventHandler<AckEventArgs>>(ref AckReceivedEventHandler, value);
|
||||
LazyEventBinder.UnhookMirandaEvent(ME_PROTO_ACK, AckReceivedEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public static int ChainSend(ContactChainData chainData)
|
||||
{
|
||||
if (chainData == null)
|
||||
throw new ArgumentNullException("chainData");
|
||||
|
||||
return ChainSend(chainData.WParam, chainData.CcsDataPtr);
|
||||
}
|
||||
|
||||
public static int ChainSend(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return MirandaContext.Current.CallService(MS_PROTO_CHAINSEND, wParam, lParam);
|
||||
}
|
||||
|
||||
public static int ChainReceive(ContactChainData chainData)
|
||||
{
|
||||
if (chainData == null)
|
||||
throw new ArgumentNullException("chainData");
|
||||
|
||||
return ChainReceive(chainData.WParam, chainData.CcsDataPtr);
|
||||
}
|
||||
|
||||
public static int ChainReceive(UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
return MirandaContext.Current.CallService(MS_PROTO_CHAINRECV, wParam, lParam);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure.Protocols
|
||||
{
|
||||
public sealed class ContactChainData
|
||||
{
|
||||
#region .ctors
|
||||
|
||||
internal unsafe ContactChainData(IntPtr pCcsData)
|
||||
{
|
||||
if (pCcsData == IntPtr.Zero)
|
||||
throw new ArgumentNullException("pCssData");
|
||||
|
||||
this.ccsDataPtr = pCcsData;
|
||||
|
||||
CCSDATA ccsData = *(CCSDATA*)pCcsData.ToPointer();
|
||||
this.contactInfo = ContactInfo.FromHandle(ccsData.ContactHandle);
|
||||
this.wParam = ccsData.WParam;
|
||||
this.lParam = ccsData.LParam;
|
||||
this.serviceName = Translate.ToString(ccsData.ServiceNamePtr, StringEncoding.Ansi);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private ContactInfo contactInfo;
|
||||
public ContactInfo ContactInfo
|
||||
{
|
||||
get { return contactInfo; }
|
||||
}
|
||||
|
||||
private string serviceName;
|
||||
public string ServiceName
|
||||
{
|
||||
get { return serviceName; }
|
||||
}
|
||||
|
||||
private UIntPtr wParam;
|
||||
[CLSCompliant(false)]
|
||||
public UIntPtr WParam
|
||||
{
|
||||
get { return wParam; }
|
||||
}
|
||||
|
||||
private IntPtr lParam;
|
||||
public IntPtr LParam
|
||||
{
|
||||
get { return lParam; }
|
||||
}
|
||||
|
||||
private IntPtr ccsDataPtr;
|
||||
internal IntPtr CcsDataPtr
|
||||
{
|
||||
get { return ccsDataPtr; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public string GetLParamAsString(StringEncoding encoding)
|
||||
{
|
||||
return Translate.ToString(LParam, encoding);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using System.Runtime.InteropServices;
|
||||
using Virtuoso.Miranda.Plugins.Helpers;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure.Protocols
|
||||
{
|
||||
public sealed class ManagedProtocol : Protocol
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string MS_PROTO_ADDTOCONTACT = "Proto/AddToContact";
|
||||
|
||||
private bool Registered;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
internal ManagedProtocol(string name, ProtocolType type) : base(name, type) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private PROTOCOLDESCRIPTOR nativeDescriptor;
|
||||
public PROTOCOLDESCRIPTOR NativeDescriptor
|
||||
{
|
||||
get { return nativeDescriptor; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
internal void Register()
|
||||
{
|
||||
if (Registered)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
PROTOCOLDESCRIPTOR descriptor = new PROTOCOLDESCRIPTOR(Name, Type);
|
||||
UnmanagedStructHandle<PROTOCOLDESCRIPTOR> nativeHandle = UnmanagedStructHandle<PROTOCOLDESCRIPTOR>.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
nativeHandle = new UnmanagedStructHandle<PROTOCOLDESCRIPTOR>(ref descriptor);
|
||||
int result = Context.CallService(MirandaServices.MS_PROTO_REGISTERMODULE, UIntPtr.Zero, nativeHandle.IntPtr);
|
||||
|
||||
if (result != 0)
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, result.ToString()));
|
||||
|
||||
this.nativeDescriptor = descriptor;
|
||||
Registered = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
nativeHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
internal void Unregister()
|
||||
{
|
||||
if (!Registered)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
// Currently, nothing else to do
|
||||
}
|
||||
|
||||
public void AddToContact(ContactInfo contact)
|
||||
{
|
||||
if (contact == null)
|
||||
throw new ArgumentNullException("contact");
|
||||
|
||||
AddToContact(contact.MirandaHandle);
|
||||
}
|
||||
|
||||
public void AddToContact(IntPtr contactHandle)
|
||||
{
|
||||
int result = Context.CallService(MS_PROTO_ADDTOCONTACT, contactHandle, NativeDescriptor.Name);
|
||||
|
||||
if (result != 0)
|
||||
throw new MirandaException(String.Format(TextResources.ExceptionMsg_Formatable2_MirandaServiceReturnedFailure, MS_PROTO_ADDTOCONTACT, result.ToString()));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public enum DatabaseSettingType : byte
|
||||
{
|
||||
Deleted = 0, //this setting just got deleted, no other values are valid
|
||||
Byte = 1, //bVal and cVal are valid
|
||||
UInt16 = 2, //wVal and sVal are valid
|
||||
UInt32 = 4, //dVal and lVal are valid
|
||||
AsciiString = 255, //pszVal is valid
|
||||
Blob = 254, //cpbVal and pbVal are valid
|
||||
UTF8String = 253, //pszVal is valid
|
||||
UnicodeString = 252, //pszVal is valid
|
||||
}
|
||||
|
||||
public enum ProtocolType : int
|
||||
{
|
||||
Ignore = 50, // added during v0.3.3
|
||||
Protocol = 1000,
|
||||
Encryption = 2000,
|
||||
Filter = 3000,
|
||||
Translation = 4000,
|
||||
Other = 10000 //avoid using this if at all possible
|
||||
}
|
||||
|
||||
internal enum ProtocolFlagsKind : int
|
||||
{
|
||||
/// <summary>
|
||||
/// The network capabilities that the protocol supports.
|
||||
/// </summary>
|
||||
Capabilities = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The status modes that the protocol supports.
|
||||
/// </summary>
|
||||
StatusModes = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The status modes that the protocol supports away-style messages for. Uses the <see cref="StatusModes"/> flags.
|
||||
/// </summary>
|
||||
AwayStatusModes = 3
|
||||
}
|
||||
|
||||
[Flags, CLSCompliant(false)]
|
||||
public enum ProtocolCapabilities : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// None.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Supports IM sending.
|
||||
/// </summary>
|
||||
IMSend = 0x00000001,
|
||||
/// <summary>
|
||||
/// Supports IM receiving.
|
||||
/// </summary>
|
||||
IMReceive = 0x00000002,
|
||||
IM = (IMSend | IMReceive),
|
||||
/// <summary>
|
||||
/// Aupports separate URL sending.
|
||||
/// </summary>
|
||||
UrlSend = 0x00000004,
|
||||
/// <summary>
|
||||
/// Supports separate URL receiving.
|
||||
/// </summary>
|
||||
UrlReceive = 0x00000008,
|
||||
Url = (UrlSend | UrlReceive),
|
||||
/// <summary>
|
||||
/// Supports file sending.
|
||||
/// </summary>
|
||||
FileSend = 0x00000010,
|
||||
/// <summary>
|
||||
/// Supports file receiving.
|
||||
/// </summary>
|
||||
FileReceive = 0x00000020,
|
||||
File = (FileSend | FileReceive),
|
||||
/// <summary>
|
||||
/// Supports broadcasting away messages.
|
||||
/// </summary>
|
||||
ModeMessageSend = 0x00000040,
|
||||
/// <summary>
|
||||
/// Supports reading others' away messages.
|
||||
/// </summary>
|
||||
ModeMessageReceive = 0x00000080,
|
||||
ModeMessage = (ModeMessageSend | ModeMessageReceive),
|
||||
/// <summary>
|
||||
/// Contact lists are stored on the server, not locally. See notes below.
|
||||
/// </summary>
|
||||
ServerContactList = 0x00000100,
|
||||
/// <summary>
|
||||
/// Will get authorisation requests for some or all contacts.
|
||||
/// </summary>
|
||||
AuthorizationRequired = 0x00000200,
|
||||
/// <summary>
|
||||
/// Will get 'you were added' notifications.
|
||||
/// </summary>
|
||||
Added = 0x00000400,
|
||||
/// <summary>
|
||||
/// Has an invisible list.
|
||||
/// </summary>
|
||||
VisibleList = 0x00000800,
|
||||
/// <summary>
|
||||
/// Has a visible list for when in invisible mode.
|
||||
/// </summary>
|
||||
InvisibleList = 0x00001000,
|
||||
/// <summary>
|
||||
/// Supports setting different status modes to each contact.
|
||||
/// </summary>
|
||||
IndividualStatus = 0x00002000,
|
||||
/// <summary>
|
||||
/// the protocol is extensible and Supports plugin-defined messages.
|
||||
/// </summary>
|
||||
Extensible = 0x00004000,
|
||||
/// <summary>
|
||||
/// Supports direct (not server mediated) communication between clients.
|
||||
/// </summary>
|
||||
P2P = 0x00008000,
|
||||
/// <summary>
|
||||
/// Supports creation of new user IDs.
|
||||
/// </summary>
|
||||
NewUser = 0x00010000,
|
||||
/// <summary>
|
||||
/// Has a realtime chat capability.
|
||||
/// </summary>
|
||||
Chat = 0x00020000,
|
||||
/// <summary>
|
||||
/// Supports replying to a mode message request with different text depending on the contact requesting.
|
||||
/// </summary>
|
||||
IndividualModeMessage = 0x00040000,
|
||||
/// <summary>
|
||||
/// Supports a basic user searching facility.
|
||||
/// </summary>
|
||||
BasicSearch = 0x00080000,
|
||||
/// <summary>
|
||||
/// Supports one or more protocol-specific extended search schemes.
|
||||
/// </summary>
|
||||
ExtendedSearch = 0x00100000,
|
||||
/// <summary>
|
||||
/// Supports renaming of incoming files as they are transferred.
|
||||
/// </summary>
|
||||
CanRenameFile = 0x00200000,
|
||||
/// <summary>
|
||||
/// Can resume broken file transfers.
|
||||
/// </summary>
|
||||
FileResume = 0x00400000,
|
||||
/// <summary>
|
||||
/// Can add search results to the contact list.
|
||||
/// </summary>
|
||||
AddSearches = 0x00800000,
|
||||
/// <summary>
|
||||
/// Can send contacts to other users.
|
||||
/// </summary>
|
||||
ContactSend = 0x01000000,
|
||||
/// <summary>
|
||||
/// Can receive contacts from other users.
|
||||
/// </summary>
|
||||
ContactReceive = 0x02000000,
|
||||
Contact = (ContactSend | ContactReceive),
|
||||
/// <summary>
|
||||
/// Can change our user information stored on server.
|
||||
/// </summary>
|
||||
ChangeInfo = 0x04000000,
|
||||
/// <summary>
|
||||
/// Supports a search by e-mail feature.
|
||||
/// </summary>
|
||||
SearchByEmail = 0x08000000,
|
||||
/// <summary>
|
||||
/// Set if the uniquely identifying field of the network is the e-mail address.
|
||||
/// </summary>
|
||||
UserIDIsEmail = 0x10000000,
|
||||
/// <summary>
|
||||
/// Supports searching by nick/first/last names.
|
||||
/// </summary>
|
||||
SearchByName = 0x20000000,
|
||||
/// <summary>
|
||||
/// Has a dialog box to allow searching all the possible fields.
|
||||
/// </summary>
|
||||
ExtendedSearchUI = 0x40000000,
|
||||
/// <summary>
|
||||
/// The unique user IDs for this protocol are numeric.
|
||||
/// </summary>
|
||||
NumericUserID = 0x80000000,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ProtocolStatusModes : int
|
||||
{
|
||||
Online = 0x00000001, //an unadorned online mode
|
||||
Invisible = 0x00000002,
|
||||
ShortAway = 0x00000004, //Away on ICQ, BRB on MSN
|
||||
LongAway = 0x00000008, //NA on ICQ, Away on MSN
|
||||
LightDND = 0x00000010, //Occupied on ICQ, Busy on MSN
|
||||
HeavyDND = 0x00000020, //DND on ICQ
|
||||
FreeForChat = 0x00000040,
|
||||
OutToLunch = 0x00000080,
|
||||
OnThePhone = 0x00000100,
|
||||
Idle = 0x00000200 //added during 0.3.4 (2004/09/13)
|
||||
}
|
||||
|
||||
public enum DatabaseEventType : short
|
||||
{
|
||||
Message = 0,
|
||||
Url = 1,
|
||||
Contacts = 2, //v0.1.2.2+
|
||||
Added = 1000, //v0.1.1.0+: these used to be module-
|
||||
AuthorizationRequest = 1001, //specific codes, hence the module-
|
||||
File = 1002, //specific limit has been raised to 2000
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum DatabaseEventProperties : int
|
||||
{
|
||||
None = 0,
|
||||
|
||||
First = 1, //this is the first event in the chain;
|
||||
//internal only: *do not* use this flag
|
||||
Sent = 2, //this event was sent by the user. If not set this
|
||||
//event was received.
|
||||
Read = 4, //event has been read by the user. It does not need
|
||||
//to be processed any more except for history.
|
||||
|
||||
Rtl = 8, //event contains the right-to-left aligned text
|
||||
Utf8 = 16 //event contains a text in utf-8
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum MenuItemProperties : int
|
||||
{
|
||||
KeepCurrent = -1,
|
||||
None = 0,
|
||||
Grayed = 1,
|
||||
Checked = 2,
|
||||
Hidden = 4,
|
||||
OnlineOnly = 8,
|
||||
OfflineOnly = 16,
|
||||
NotOnListOnly = 32,
|
||||
NonNotOnListOnly = 64
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum HotKeys : int
|
||||
{
|
||||
Alt = 0x0001,
|
||||
Ctrl = 0x0002,
|
||||
Shift = 0x0004,
|
||||
WinKey = 0x0008
|
||||
}
|
||||
|
||||
public enum ContactInfoPropertyType : int
|
||||
{
|
||||
Unknown = 0,
|
||||
Byte = 1,
|
||||
UInt16 = 2,
|
||||
UInt32 = 3,
|
||||
String = 4
|
||||
}
|
||||
|
||||
public static class CallbackResult
|
||||
{
|
||||
public const int Success = 0;
|
||||
public const int Failure = -1;
|
||||
}
|
||||
|
||||
public static class EventResult
|
||||
{
|
||||
public const bool HonourEventChain = false;
|
||||
public const bool BreakEventChain = true;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ContactListEventProperties : int
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Flashes the icon even if the user is occupied, and puts the event at the top of the queue.
|
||||
/// </summary>
|
||||
Urgent = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The icon will not flash for ever, only a few times. This is for eg online alert.
|
||||
/// </summary>
|
||||
Minor = 2,
|
||||
|
||||
// #define CLEF_URGENT 1 //flashes the icon even if the user is occupied,
|
||||
// //and puts the event at the top of the queue
|
||||
//#define CLEF_ONLYAFEW 2 //the icon will not flash for ever, only a few
|
||||
// //times. This is for eg online alert
|
||||
//#define CLEF_UNICODE 4 //set pszTooltip as unicode
|
||||
|
||||
//#define CLEF_PROTOCOLGLOBAL 8 //set event globally for protocol, hContact has to be NULL,
|
||||
// //lpszProtocol the protocol ID name to be set
|
||||
|
||||
//#if defined( _UNICODE )
|
||||
// #define CLEF_TCHAR CLEF_UNICODE //will use TCHAR* instead of char*
|
||||
//#else
|
||||
// #define CLEF_TCHAR 0 //will return char*, as usual
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public abstract class RemoteObject : MarshalByRefObject
|
||||
{
|
||||
protected RemoteObject() { }
|
||||
|
||||
public override object InitializeLifetimeService()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
internal static class RuntimeCaches
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static readonly Dictionary<string, object> Caches = new Dictionary<string, object>(1);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Getters
|
||||
|
||||
public static IDictionary<TKey, TValue> GetCache<TKey, TValue>(string cacheName)
|
||||
{
|
||||
return GetCache(cacheName) as IDictionary<TKey, TValue>;
|
||||
}
|
||||
|
||||
public static object GetCache(string name)
|
||||
{
|
||||
if (Caches.ContainsKey(name))
|
||||
throw new ArgumentException("Cache not found.", "name");
|
||||
|
||||
return Caches[name];
|
||||
}
|
||||
|
||||
public static bool CacheRegistered(string name)
|
||||
{
|
||||
return Caches.ContainsKey(name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Setters
|
||||
|
||||
public static void RegisterCache(string name, object cache)
|
||||
{
|
||||
if (Caches.ContainsKey(name))
|
||||
throw new ArgumentException("Cache already registered.", "name");
|
||||
|
||||
Caches[name] = cache;
|
||||
}
|
||||
|
||||
public static bool UnregisterCache(string name)
|
||||
{
|
||||
return Caches.Remove(name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Hyphen;
|
||||
using System.Threading;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides information about current state of Hyphen runtime.
|
||||
/// This class can be used only from the context of standalone modules (i.e. from the default AppDomain only).
|
||||
/// </summary>
|
||||
public static class RuntimeEnvironment
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static volatile bool Initialized;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Marks the class initialized.
|
||||
/// </summary>
|
||||
internal static void Initialize()
|
||||
{
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies whether the class was initialized (from the default AppDomain).
|
||||
/// </summary>
|
||||
/// <exception cref="NotSupportedException">Class not initialized (i.e. called from other than default AppDomain).</exception>
|
||||
private static void VerifyInitialized()
|
||||
{
|
||||
if (!Initialized)
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
private static bool hyphenIsLoading;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an indication whether the Hyphen runtime is currently loading.
|
||||
/// </summary>
|
||||
/// <exception cref="NotSupportedException">Class not initialized (i.e. called from other than default AppDomain).</exception>
|
||||
public static bool HyphenIsLoading
|
||||
{
|
||||
get { VerifyInitialized(); return hyphenIsLoading; }
|
||||
internal set { hyphenIsLoading = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an indication whether the Isolated plugins are loaded.
|
||||
/// </summary>
|
||||
/// <exception cref="NotSupportedException">Class not initialized (i.e. called from other than default AppDomain).</exception>
|
||||
public static bool IsolatedModePluginsLoaded
|
||||
{
|
||||
get { VerifyInitialized(); return Loader.GetInstance().PluginsLoaded; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public sealed class ServiceCallInterceptionManager
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private readonly Dictionary<string, Callback> Interceptors;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
public ServiceCallInterceptionManager()
|
||||
{
|
||||
this.Interceptors = new Dictionary<string, Callback>(2);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public bool RequiresInterception(string serviceName)
|
||||
{
|
||||
lock (Interceptors)
|
||||
return Interceptors.ContainsKey(serviceName);
|
||||
}
|
||||
|
||||
public Callback this[string serviceName]
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (Interceptors)
|
||||
{
|
||||
Callback interceptor = null;
|
||||
Interceptors.TryGetValue(serviceName, out interceptor);
|
||||
|
||||
return interceptor;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
Register(serviceName, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Register(string serviceName, Callback interceptor)
|
||||
{
|
||||
lock (Interceptors)
|
||||
Interceptors[serviceName] = interceptor;
|
||||
}
|
||||
|
||||
public void Unregister(string serviceName)
|
||||
{
|
||||
lock (Interceptors)
|
||||
Interceptors.Remove(serviceName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||
public sealed class ServiceFunctionAttribute : HookAttribute
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private string serviceName;
|
||||
public string ServiceName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.serviceName;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.serviceName = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal override string HookName
|
||||
{
|
||||
get { return ServiceName; }
|
||||
}
|
||||
|
||||
internal override HookType HookType
|
||||
{
|
||||
get { return HookType.ServiceFunction; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
public ServiceFunctionAttribute(string serviceName)
|
||||
{
|
||||
if (serviceName == null)
|
||||
throw new ArgumentNullException("serviceName");
|
||||
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Collections;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public static class ServiceManager
|
||||
{
|
||||
[CLSCompliant(false)]
|
||||
public static void CreateServiceFunction(string serviceName, Callback callback, MirandaPlugin owner)
|
||||
{
|
||||
if (String.IsNullOrEmpty(serviceName))
|
||||
throw new ArgumentNullException("serviceName");
|
||||
|
||||
if (callback == null)
|
||||
throw new ArgumentNullException("callback");
|
||||
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (!owner.Initialized)
|
||||
throw new InvalidOperationException(TextResources.ExceptionMsg_PluginNotInitialized);
|
||||
|
||||
HookDescriptorCollection collection = owner.Descriptor.ServiceFunctions;
|
||||
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginPluginUpdate(owner);
|
||||
SynchronizationHelper.BeginCollectionUpdate(collection);
|
||||
|
||||
HookDescriptor descriptor = HookDescriptor.SetUpAndStore(collection, serviceName, owner.Descriptor, callback, HookType.ServiceFunction);
|
||||
descriptor.RegisteredManually = true;
|
||||
|
||||
HookManager.CreateHook(descriptor);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(owner);
|
||||
SynchronizationHelper.EndUpdate(collection);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ServiceExists(string name)
|
||||
{
|
||||
return MirandaContext.Current.PluginLink.NativePluginLink.ServiceExists(name) != 0;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static Callback GetService(string serviceName)
|
||||
{
|
||||
return CallbackWrapper.Create(serviceName);
|
||||
}
|
||||
|
||||
public static void RemoveServiceFunction(MirandaPlugin owner, string eventName)
|
||||
{
|
||||
if (owner == null)
|
||||
throw new ArgumentNullException("owner");
|
||||
|
||||
if (String.IsNullOrEmpty(eventName))
|
||||
throw new ArgumentNullException("eventName");
|
||||
|
||||
HookDescriptorCollection collection = owner.Descriptor.ServiceFunctions;
|
||||
|
||||
try
|
||||
{
|
||||
SynchronizationHelper.BeginCollectionUpdate(collection);
|
||||
HookDescriptor descriptor = null;
|
||||
|
||||
if ((descriptor = collection.Find(eventName)) == null)
|
||||
return;
|
||||
|
||||
HookManager.DestroyHook(descriptor);
|
||||
collection.Remove(descriptor);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SynchronizationHelper.EndUpdate(collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages Miranda skin entities, for example icons and sounds.
|
||||
/// </summary>
|
||||
/// <mHeader>m_skin.h</mHeader>
|
||||
public static class Skin
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string MS_SKIN_LOADICON = "Skin/Icons/Load",
|
||||
MS_SKIN_LOADPROTOICON = "Skin/Icons/LoadProto";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Icons
|
||||
|
||||
public static class Icons
|
||||
{
|
||||
public const int Message = 100;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public static IntPtr LoadIcon(int id)
|
||||
{
|
||||
return (IntPtr)MirandaContext.Current.CallService(MS_SKIN_LOADICON, (UIntPtr)(uint)id, IntPtr.Zero);
|
||||
}
|
||||
|
||||
public static IntPtr LoadProtocolIcon(StatusMode status)
|
||||
{
|
||||
return LoadProtocolIcon((string)null, status);
|
||||
}
|
||||
|
||||
public static IntPtr LoadProtocolIcon(Protocol protocol, StatusMode status)
|
||||
{
|
||||
return LoadProtocolIcon((protocol != null ? protocol.Name : null), status);
|
||||
}
|
||||
|
||||
public static IntPtr LoadProtocolIcon(string protocolName, StatusMode status)
|
||||
{
|
||||
UnmanagedStringHandle protoNamePtr = UnmanagedStringHandle.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
protoNamePtr = new UnmanagedStringHandle(protocolName, StringEncoding.Ansi);
|
||||
return (IntPtr)MirandaContext.Current.CallService(MS_SKIN_LOADPROTOICON, protoNamePtr.IntPtr, (IntPtr)status);
|
||||
}
|
||||
finally
|
||||
{
|
||||
protoNamePtr.Free();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Helpers;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
public enum StatusMode : int
|
||||
{
|
||||
Offline = 40071,
|
||||
Online = 40072,
|
||||
Away = 40073,
|
||||
DND = 40074,
|
||||
NA = 40075,
|
||||
Occupied = 40076,
|
||||
|
||||
[EnumValueFriendlyName("Free for chat")]
|
||||
FreeForChat = 40077,
|
||||
Invisible = 40078,
|
||||
|
||||
[EnumValueFriendlyName("On the phone")]
|
||||
OnThePhone = 40079,
|
||||
|
||||
[EnumValueFriendlyName("Out to lunch")]
|
||||
OutToLunch = 40080,
|
||||
|
||||
Idle = 40081 /* do not use as a status */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Helpers;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
internal sealed class StringResolverCache : TypeInstanceCache<IStringResolver>
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static StringResolverCache singleton;
|
||||
|
||||
#endregion
|
||||
|
||||
#region .ctors
|
||||
|
||||
private StringResolverCache() { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public static StringResolverCache Singleton
|
||||
{
|
||||
get
|
||||
{
|
||||
return singleton ?? (singleton = new StringResolverCache());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/***********************************************************************\
|
||||
* Virtuoso.Miranda.Plugins (Hyphen) *
|
||||
* Provides a managed wrapper for API of IM client Miranda. *
|
||||
* Copyright (C) 2006-2009 virtuoso *
|
||||
* deml.tomas@seznam.cz *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
\***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Virtuoso.Miranda.Plugins.Infrastructure;
|
||||
using Virtuoso.Miranda.Plugins.Resources;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using Virtuoso.Miranda.Plugins.Native;
|
||||
|
||||
namespace Virtuoso.Miranda.Plugins.Infrastructure
|
||||
{
|
||||
[CLSCompliant(false)]
|
||||
public static class Translate
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static readonly Type StatusEnumType = typeof(StatusMode);
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToStatus
|
||||
|
||||
public static StatusMode ToStatus(UIntPtr wParam)
|
||||
{
|
||||
if (!Enum.IsDefined(StatusEnumType, (int)wParam.ToUInt32()))
|
||||
throw new ArgumentException("wParam", TextResources.ExceptionMsg_InvalidValueToTranslate);
|
||||
|
||||
return (StatusMode)(wParam);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToString
|
||||
|
||||
public static string ToString(IntPtr lParam, StringEncoding marshalAs)
|
||||
{
|
||||
return ToString(lParam, 0, marshalAs, false);
|
||||
}
|
||||
|
||||
public static string ToString(IntPtr lParam, StringEncoding marshalAs, bool transformExceptionsToNull)
|
||||
{
|
||||
return ToString(lParam, 0, marshalAs, transformExceptionsToNull);
|
||||
}
|
||||
|
||||
public static string ToString(IntPtr lParam, int length, StringEncoding marshalAs)
|
||||
{
|
||||
return ToString(lParam, length, marshalAs, false);
|
||||
}
|
||||
|
||||
public static string ToString(IntPtr lParam, int length, StringEncoding marshalAs, bool tranformExceptionsToNull)
|
||||
{
|
||||
if (lParam == IntPtr.Zero)
|
||||
throw new ArgumentNullException("lParam");
|
||||
|
||||
if (length < 0)
|
||||
throw new ArgumentOutOfRangeException("length");
|
||||
|
||||
if (marshalAs != StringEncoding.MirandaDefault && marshalAs != StringEncoding.Ansi && marshalAs != StringEncoding.Unicode)
|
||||
throw new ArgumentOutOfRangeException("marshalAs");
|
||||
|
||||
try
|
||||
{
|
||||
reEval:
|
||||
switch (marshalAs)
|
||||
{
|
||||
case StringEncoding.MirandaDefault:
|
||||
marshalAs = MirandaEnvironment.MirandaStringEncoding;
|
||||
if (marshalAs == StringEncoding.MirandaDefault) throw new ArgumentException(TextResources.ExceptionMsg_CannotDetectMirandaDefaultStringEncoding);
|
||||
goto reEval;
|
||||
case StringEncoding.Ansi:
|
||||
if (length > 0)
|
||||
return Marshal.PtrToStringAnsi(lParam, length);
|
||||
else
|
||||
return Marshal.PtrToStringAnsi(lParam);
|
||||
case StringEncoding.Unicode:
|
||||
if (length > 0)
|
||||
return Marshal.PtrToStringUni(lParam, length);
|
||||
else
|
||||
return Marshal.PtrToStringUni(lParam);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (!tranformExceptionsToNull)
|
||||
throw new ArgumentException("lParam", TextResources.ExceptionMsg_InvalidValueToTranslate + e.Message, e);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToHandle
|
||||
|
||||
public static IntPtr ToHandle(UIntPtr wParam)
|
||||
{
|
||||
return new IntPtr((long)wParam.ToUInt64());
|
||||
}
|
||||
|
||||
public static UIntPtr ToHandle(IntPtr lParam)
|
||||
{
|
||||
return new UIntPtr((ulong)lParam.ToInt64());
|
||||
}
|
||||
|
||||
public static UnmanagedStringHandle ToHandle(string str, StringEncoding encoding)
|
||||
{
|
||||
return new UnmanagedStringHandle(str, encoding);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region To/From Miranda HyphenVersion Format
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static uint ToMirandaVersion(Version version)
|
||||
{
|
||||
if (version == null)
|
||||
throw new ArgumentNullException("version");
|
||||
|
||||
return (((((uint)(version.Major)) & 0xFF) << 24) | ((((uint)(version.Minor)) & 0xFF) << 16) | ((((uint)(version.Build)) & 0xFF) << 8) | (((uint)(version.MinorRevision)) & 0xFF));
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static Version FromMirandaVersion(uint version)
|
||||
{
|
||||
return new Version((int)((version >> 24) & 0xff), (int)((version >> 16) & 0xff), (int)((version >> 8) & 0xff), (int)(version & 0xff));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Misc.
|
||||
|
||||
public static byte[] ToBlob(IntPtr blobPtr, int size)
|
||||
{
|
||||
if (blobPtr == IntPtr.Zero)
|
||||
throw new ArgumentNullException("blobPtr");
|
||||
|
||||
if (size < 0)
|
||||
throw new ArgumentOutOfRangeException("size");
|
||||
|
||||
byte[] blob = new byte[size];
|
||||
Marshal.Copy(blobPtr, blob, 0, size);
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal helpers
|
||||
|
||||
internal static object ValueFromVariant(ref DBVARIANT dbVariant)
|
||||
{
|
||||
switch ((DbVariantValue)dbVariant.Type)
|
||||
{
|
||||
case DbVariantValue.DBVT_ASCIIZ:
|
||||
return Translate.ToString(dbVariant.Text.TextPtr, dbVariant.Text.TextBufferSize, StringEncoding.Ansi);
|
||||
case DbVariantValue.DBVT_UTF8:
|
||||
return Translate.ToString(dbVariant.Text.TextPtr, dbVariant.Text.TextBufferSize, StringEncoding.Unicode);
|
||||
case DbVariantValue.DBVT_BLOB:
|
||||
return ToBlob(dbVariant.Blob.BlobPtr, dbVariant.Blob.Size);
|
||||
case DbVariantValue.DBVT_BYTE:
|
||||
return dbVariant.Primitives.Byte;
|
||||
case DbVariantValue.DBVT_DELETED:
|
||||
return null;
|
||||
case DbVariantValue.DBVT_DWORD:
|
||||
return dbVariant.Primitives.DWord;
|
||||
case DbVariantValue.DBVT_WORD:
|
||||
return dbVariant.Primitives.Word;
|
||||
case DbVariantValue.DBVT_WCHAR:
|
||||
return Marshal.PtrToStringBSTR(dbVariant.Text.TextPtr);
|
||||
case DbVariantValue.DBVTF_VARIABLELENGTH:
|
||||
throw new NotSupportedException();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user