diff options
Diffstat (limited to 'plugins/ShlExt')
41 files changed, 3621 insertions, 9997 deletions
diff --git a/plugins/ShlExt/inc/README.txt b/plugins/ShlExt/inc/README.txt deleted file mode 100644 index 4c0ab5f0cf..0000000000 --- a/plugins/ShlExt/inc/README.txt +++ /dev/null @@ -1,92 +0,0 @@ -
- - Miranda Module API for Borland Delphi, FreePascal -
-
- These include files allow you to write modules to extend Miranda
- Older versions of these files
- limited support for FPC, versions & compilers are :
-
- Borland Delphi 2.0 thru 6.0
- FreePascal 1.0.4, 1.0.6
-
- You can now create modules for Miranda (v0.1.2.2) and use
- new stuff like Netlib! though you can still write for
- the current stable release (v0.1.2.1) but you'll have to
- be aware of version dependant things.
-
- Worry not though, every service/event is marked with a version
- code if it's not present in older Miranda versions.
-
- Be warned, this is a brand new porting though it has borrowed
- from older ports (see CVS, oh this is viewCVS? mmm, cheese.)
- Things are presented in a more Delphi esque than a C esque manner
- so if you feel confused refer to the C header.
-
- A word of warning, don't try to compile /delphiplugins examples
- with these include files and expect it to work,
-
-
- Include files use the {$include } syntax and will never work
- as units.
-
- -- FPC support? --
-
- FPC is now properly supported, but you may need to use -SD -S2
- command line switches (for Delphi, BP7 mode) remember to use -Fi
- and -Fu to give the path to these files or use {$UNITPATH} and {$INCLUDEPATH}
-
- These include files don't any FPC stuff like macros
- and inlined functions.
-
- -- Things to be aware of --
-
- This version is not yet directly supported, if you want to learn
- the API look at the CVS tree for documentation on plugins, as well
- as guidelines and examples of the general structure of Miranda.
-
- This is my cop out for now, I'll try to write a more general 'guide' later
- on.
-
- -
-
- Miranda uses a manifest to allow COMCTRL v6 to be loaded on XP,
- This causes problems with image lists with Delphi (there are work arounds)
- see borland.com for the article.
-
- You may want to refuse to load on XP or try to use Miranda's API to work with
- imagelists and load images from resource as bitmaps (ugh)
-
- - lstrcat, lstrcpy
-
- I've used the Windows API calls to these C functions over Delphi's RTL
- because SysUtils.pas just adds a bloat.
-
- - *If* you use SysUtils.pas
-
- Delphi loads OLE for variant support, it maybe advisable to unload
- the DLL as soon as you start, this maybe a problem though, since Miranda
- also uses OLE for extended image support, it doesn't however keep
- it loaded all the time.
-
- There should be no problem in just decrementing the reference count
- to the DLL and it'll unload if you were the only reference.
-
- if however you're using variants in your code, blergh.
-
- -- How you get it to work --
-
- see testdll.dpr, it won't do much but it'll show a pretty description in the
- options dialog (oh impressive!)
-
- To bring in new files, just use {$include that_file_you_want.inc}
- If other include files are needed by the include file you bring in,
- it'll try to include it itself.
-
- Of course you need to add the path to where the .inc files are to the project's
- search path, or if you compile via the command line, use -U and -I
- -U is needed because m_globaldefs.pas is a unit.
-
- Each header file is marked with "UNITDEP" which will tell you which units
- it requires.
-
- All files that require the PLUGINLINK structure require m_globaldefs.pas
- (this is all the C header files that use such macros!)
diff --git a/plugins/ShlExt/inc/m_addcontact.inc b/plugins/ShlExt/inc/m_addcontact.inc deleted file mode 100644 index 2e74ad1279..0000000000 --- a/plugins/ShlExt/inc/m_addcontact.inc +++ /dev/null @@ -1,54 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_ADDCONTACT}
-{$DEFINE M_ADDCONTACT}
-
-const
-
- HANDLE_SEARCHRESULT = 0;
- HANDLE_EVENT = 1;
- HANDLE_CONTACT = 2;
-
-type
-
- PADDCONTACTSTRUCT = ^TADDCONTACTSTRUCT;
- TADDCONTACTSTRUCT = record
- handleType: Integer;
- handle: THandle; // HDBEVENT, HCONTACT, SearchResult
- szProto: PChar; // used by search result only
- psr: Pointer; // @PROTOSEARCHRESULT
- end;
-
-const
-
- {
- wParam : (HWND) Parent window of the dialog that will be presented
- lParam : Pointer to an initialised TADDCONTACTSTRUCT
- Affect : Open's the add contact dialog
- Version: 0.1.2.2+
- }
- MS_ADDCONTACT_SHOW = 'AddContact/Show';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_api.pas b/plugins/ShlExt/inc/m_api.pas deleted file mode 100644 index 78fda24976..0000000000 --- a/plugins/ShlExt/inc/m_api.pas +++ /dev/null @@ -1,75 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFDEF FPC}
- {$PACKRECORDS C}
- {$MODE Delphi}
-{$ENDIF}
-
-unit m_api;
-
-interface
-
-uses
-
- m_globaldefs, windows;
-
- {$include m_plugins.inc}
- {$include m_system.inc}
- {$include m_database.inc}
- {$include m_findadd.inc}
- {$include m_awaymsg.inc}
- {$include m_email.inc}
- {$include m_history.inc}
- {$include m_message.inc}
- {$include m_url.inc}
- {$include newpluginapi.inc}
- {$include m_clui.inc}
- {$include m_ignore.inc}
- {$include m_skin.inc}
- {$include m_file.inc}
- {$include m_netlib.inc}
- {$include m_langpack.inc}
- {$include m_clist.inc}
- {$include m_clc.inc}
- {$include m_userinfo.inc}
- {$include m_protosvc.inc}
- {$include m_options.inc}
- {$include m_icq.inc}
- {$include m_protocols.inc}
- {$include m_protomod.inc}
- {$include m_utils.inc}
- {$include m_addcontact.inc}
- {$include statusmodes.inc}
- {$include m_contacts.inc}
- {$define M_API_UNIT}
- {$include m_helpers.inc}
-
-implementation
-
- {$undef M_API_UNIT}
- {$include m_helpers.inc}
-
-end.
-
diff --git a/plugins/ShlExt/inc/m_awaymsg.inc b/plugins/ShlExt/inc/m_awaymsg.inc deleted file mode 100644 index 2ad330f9de..0000000000 --- a/plugins/ShlExt/inc/m_awaymsg.inc +++ /dev/null @@ -1,40 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_AWAYMSG}
-{$DEFINE M_AWAYMSG}
-
-const
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Show the away/na/etc message for a contact
- Returns: 0 on success, non zero on failure, see notes
- notes : returns without waiting for the message to be shown.
- version: v0.1.0.1+
- }
- MS_AWAYMSG_SHOWAWAYMSG = 'SRAway/GetMessage';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_clc.inc b/plugins/ShlExt/inc/m_clc.inc deleted file mode 100644 index d55ecc7438..0000000000 --- a/plugins/ShlExt/inc/m_clc.inc +++ /dev/null @@ -1,284 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_CLC}
-{$DEFINE M_CLC}
-
-const
-
- CLISTCONTROL_CLASS = 'CListControl';
-
- // styles
-
- CLS_MANUALUPDATE = $0001; // todo
- CLS_SHOWHIDDEN = $0002;
- CLS_HIDEOFFLINE = $0004; // hides all offline users
- CLS_CHECKBOXES = $0008;
- CLS_MULTICOLUMN = $0010; // not true multi-column, just for ignore/vis options
- CLS_HIDEEMPTYGROUPS = $0020; // note: this flag will be spontaneously removed if the 'new subgroup' menu item is clicked, for obvious reasons
- CLS_USEGROUPS = $0040;
- CLS_NOHIDEOFFLINE = $0080; // overrides CLS_HIDEOFFLINE and the per-group hideoffline setting
- CLS_GREYALTERNATE = $0100; // make every other line slightly grey
- CLS_GROUPCHECKBOXES = $0200; // put checkboxes on groups too (managed by CLC)
-
- CLS_EX_DISABLEDRAGDROP = $00000001;
- CLS_EX_EDITLABELS = $00000002;
- CLS_EX_SHOWSELALWAYS = $00000004;
- CLS_EX_TRACKSELECT = $00000008;
- CLS_EX_SHOWGROUPCOUNTS = $00000010;
- CLS_EX_DIVIDERONOFF = $00000020;
- CLS_EX_HIDECOUNTSWHENEMPTY = $00000040;
- CLS_EX_NOTRANSLUCENTSEL = $00000080;
- CLS_EX_LINEWITHGROUPS = $00000100;
- CLS_EX_QUICKSEARCHVISONLY = $00000200;
- CLS_EX_SORTGROUPSALPHA = $00000400;
- CLS_EX_NOSMOOTHSCROLLING = $00000800;
-
- CLM_FIRST = $1000; // this is the same as LVM_FIRST
- CLM_LAST = $1100;
-
-// messages, compare with equivalent TVM_* in the WINAPI
-
- CLM_ADDCONTACT = (CLM_FIRST+0); // wParam=hContact
- CLM_ADDGROUP = (CLM_FIRST+1); // wParam=hGroup
- CLM_AUTOREBUILD = (CLM_FIRST+2);
- CLM_DELETEITEM = (CLM_FIRST+3); // wParam=hItem
- CLM_EDITLABEL = (CLM_FIRST+4); // wParam=hItem
- CLM_ENDEDITLABELNOW = (CLM_FIRST+5); // wParam=cancel, 0 to save
- CLM_ENSUREVISIBLE = (CLM_FIRST+6); // wParam=hItem, lParam=partialOk
-
- CLE_TOGGLE = -1;
- CLE_COLLAPSE = 0;
- CLE_EXPAND = 1;
- CLE_INVALID = $FFFF;
-
- CLM_EXPAND = (CLM_FIRST+7); // wParam=hItem, lParam=CLE_
- CLM_FINDCONTACT = (CLM_FIRST+8); // wParam=hContact, returns an hItem
- CLM_FINDGROUP = (CLM_FIRST+9); // wParam=hGroup, returns an hItem
- CLM_GETBKCOLOR = (CLM_FIRST+10); // returns a COLORREF
- CLM_GETCHECKMARK = (CLM_FIRST+11); // wParam=hItem, returns 1 or 0
- CLM_GETCOUNT = (CLM_FIRST+12); // returns the total number of items
-
- CLM_GETEDITCONTROL = (CLM_FIRST+13); // returns the HWND, or NULL
- CLM_GETEXPAND = (CLM_FIRST+14); // wParam=hItem, returns a CLE_, CLE_INVALID if not a group
- CLM_GETEXTRACOLUMNS = (CLM_FIRST+15); // returns number of extra columns
- CLM_GETEXTRAIMAGE = (CLM_FIRST+16); // wParam=hItem, lParam=MAKELPARAM(iColumn (0 based),0), returns iImage or $FF
- CLM_GETEXTRAIMAGELIST = (CLM_FIRST+17); // returns HIMAGELIST
- CLM_GETFONT = (CLM_FIRST+18); // wParam=fontId, see clm_setfont. returns hFont.
- CLM_GETINDENT = (CLM_FIRST+19); // wParam=new group indent
- CLM_GETISEARCHSTRING = (CLM_FIRST+20); // lParam=(char*)pszStr, max 120 bytes, returns number of chars in string
- CLM_GETITEMTEXT = (CLM_FIRST+21); // wParam=hItem, lParam=(char*)pszStr, max 120 bytes
- CLM_GETSCROLLTIME = (CLM_FIRST+22); // returns time in ms
- CLM_GETSELECTION = (CLM_FIRST+23); // returns hItem
-
- CLCHT_ABOVE = $0001; // above client area
- CLCHT_BELOW = $0002; // below client area
- CLCHT_TOLEFT = $0004; // left of client area
- CLCHT_TORIGHT = $0008; // right of client area
- CLCHT_NOWHERE = $0010; // in client area, not on an item
- CLCHT_ONITEMICON = $0020;
- CLCHT_ONITEMCHECK = $0040;
- CLCHT_ONITEMLABEL = $0080;
- CLCHT_ONITEMINDENT = $0100; // to the left of an item icon
- CLCHT_ONITEMEXTRA = $0200; // on an extra icon, HIBYTE(HIWORD()) says which
- CLCHT_ONITEM = $03E0;
- CLCHT_INLEFTMARGIN = $0400;
- CLCHT_BELOWITEMS = $0800; // in client area but below last item
-
- CLM_HITTEST = (CLM_FIRST+25); // lParam=MAKELPARAM(x,y) (relative to control), wParam=(PDWORD)&hitTest (see encoding of HitTest() in clc.h, can be NULL) returns hItem or NULL
- CLM_SELECTITEM = (CLM_FIRST+26); // wParam=hItem
-
- CLB_TOPLEFT = 0;
- CLB_STRETCHV = 1;
- CLB_STRETCHH = 2; // and tile vertically
- CLB_STRETCH = 3;
-
- CLBM_TYPE = $00FF;
- CLBF_TILEH = $1000;
- CLBF_TILEV = $2000;
- CLBF_PROPORTIONAL = $4000;
- CLBF_SCROLL = $8000;
-
- CLM_SETBKBITMAP = (CLM_FIRST+27); // wParam=mode, lParam=hBitmap (don't delete it), NULL for none
- CLM_SETBKCOLOR = (CLM_FIRST+28); // wParam=a COLORREF, default is GetSysColor(COLOR_3DFACE)
- CLM_SETCHECKMARK = (CLM_FIRST+29); // wParam=hItem, lParam=1 or 0
- CLM_SETEXTRACOLUMNS = (CLM_FIRST+30); // wParam=number of extra columns (zero to MAXEXTRACOLUMNS from clc.h, currently 16)
- CLM_SETEXTRAIMAGE = (CLM_FIRST+31); // wParam=hItem, lParam=MAKELPARAM(iColumn (0 based),iImage). iImage=$FF is a blank
- CLM_SETEXTRAIMAGELIST = (CLM_FIRST+32); // lParam=HIMAGELIST
-
- FONTID_CONTACTS = 0;
- FONTID_INVIS = 1;
- FONTID_OFFLINE = 2;
- FONTID_NOTONLIST = 3;
- FONTID_GROUPS = 4;
- FONTID_GROUPCOUNTS = 5;
- FONTID_DIVIDERS = 6;
- FONTID_OFFINVIS = 7;
- FONTID_MAX = 7;
-
- CLM_SETFONT = (CLM_FIRST+33); // wParam=hFont, lParam=MAKELPARAM(fRedraw,fontId)
- CLM_SETINDENT = (CLM_FIRST+34); // wParam=new indent, default is 3 pixels
- CLM_SETITEMTEXT = (CLM_FIRST+35); // wParam=hItem, lParam=(char*)pszNewText
- CLM_SETSCROLLTIME = (CLM_FIRST+36); // wParam=time in ms, default 200
- CLM_SETHIDEEMPTYGROUPS = (CLM_FIRST+38); // wParam=TRUE/FALSE
-
- GREYF_UNFOCUS = $80000000;
- MODEF_OFFLINE = $40000000;
-
- // and use the PF2_ #defines from m_protosvc.inc
- CLM_SETGREYOUTFLAGS = (CLM_FIRST+39); // wParam=new flags
- CLM_GETHIDEOFFLINEROOT = (CLM_FIRST+40); // returns TRUE/FALSE
- CLM_SETHIDEOFFLINEROOT = (CLM_FIRST+41); // wParam=TRUE/FALSE
- CLM_SETUSEGROUPS = (CLM_FIRST+42); // wParam=TRUE/FALSE
- CLM_SETOFFLINEMODES = (CLM_FIRST+43); // for 'hide offline', wParam=PF2_ flags and MODEF_OFFLINE
- CLM_GETEXSTYLE = (CLM_FIRST+44); // returns CLS_EX_ flags
- CLM_SETEXSTYLE = (CLM_FIRST+45); // wParam=CLS_EX_ flags
- CLM_GETLEFTMARGIN = (CLM_FIRST+46); // returns count of pixels
- CLM_SETLEFTMARGIN = (CLM_FIRST+47); // wParam=pixels
- // the order of info items is never changed, so make sure you add them in the
- // order you want them to remain
- CLM_ADDINFOITEM = (CLM_FIRST+48); // lParam=&TCLCINFOITEM, returns hItem
- CLM_GETITEMTYPE = (CLM_FIRST+49); // wParam=hItem, returns a CLCIT_
- CLM_GETNEXTITEM = (CLM_FIRST+50); // wParam=flag, lParam=hItem, returns an hItem
- CLM_GETTEXTCOLOR = (CLM_FIRST+51); // wParam=FONTID_, returns COLORREF
- CLM_SETTEXTCOLOR = (CLM_FIRST+52); // wParam=FONTID_, lParam=COLORREF
-
- CLCIIF_BELOWGROUPS = 1; // put it between groups and contacts, default is at top
- CLCIIF_BELOWCONTACTS = 2; // put it at the bottom
- CLCIIF_CHECKBOX = $40; // give this item a check box
- CLCIIF_GROUPFONT = $80; // draw the item using FONTID_GROUPS
-
- CLCIT_INVALID = -1;
- CLCIT_GROUP = 0;
- CLCIT_CONTACT = 1;
- CLCIT_DIVIDER = 2;
- CLCIT_INFO = 3;
-
- CLGN_ROOT = 0;
- CLGN_CHILD = 1;
- CLGN_PARENT = 2;
- CLGN_NEXT = 3;
- CLGN_PREVIOUS = 4;
- CLGN_NEXTCONTACT = 5;
- CLGN_PREVIOUSCONTACT = 6;
- CLGN_NEXTGROUP = 7;
- CLGN_PREVIOUSGROUP = 8;
-
- CLNF_ISGROUP = 1;
- CLNF_ISINFO = 2;
-
- CLN_FIRST = (0-100);
- CLN_EXPANDED = (CLN_FIRST-0); // hItem=hGroup, action=CLE_*
- CLN_LISTREBUILT = (CLN_FIRST-1);
- CLN_ITEMCHECKED = (CLN_FIRST-2); // todo // hItem,action,flags valid
- CLN_DRAGGING = (CLN_FIRST-3); // hItem,pt,flags valid. only sent when cursor outside window, return nonzero if processed
- CLN_DROPPED = (CLN_FIRST-4); // hItem,pt,flags valid. only sent when cursor outside window, return nonzero if processed
- CLN_LISTSIZECHANGE = (CLN_FIRST-5); // pt.y valid. the vertical height of the visible items in the list has changed.
- CLN_OPTIONSCHANGED = (CLN_FIRST-6); // nothing valid. If you set some extended options they have been overwritten and should be re-set
- CLN_DRAGSTOP = (CLN_FIRST-7); // hItem,flags valid. sent when cursor goes back in to the window having been outside, return nonzero if processed
- CLN_NEWCONTACT = (CLN_FIRST-8); // hItem,flags valid. sent when a new contact is added without a full list rebuild
- CLN_CONTACTMOVED = (CLN_FIRST-9); // hItem,flags valid. sent when contact is moved without a full list rebuild
- CLN_CHECKCHANGED = (CLN_FIRST-10); // hItem,flags valid. sent when any check mark is changed, but only for one change if there are many
-
-type
-
- PCLCINFOITEM = ^TCLCINFOITEM;
- TCLCINFOITEM = record
- cbSize: int;
- pszText: PChar;
- hParentGroup: THandle;
- flags: DWORD;
- hIcon: THandle; // todo
- end;
-
- PNMCLISTCONTROL = ^TNMCLISTCONTROL;
- TNMCLISTCONTROL = record
- hdr: TNMHDR; // depends on Windows.pas
- hItem: THandle;
- action: int;
- iColumn: int; // -1 if not on an extra column
- flags: DWORD;
- pt: TPoint; // depends on Windows.pas
- end;
-
- PCLCINFOTIP = ^TCLCINFOTIP;
- TCLCINFOTIP = record
- cbSize: int;
- isTreeFocused: int; // so the plugin can provide an option
- isGroup: int; // 0 if it's contact, 1 if it's a group
- hItem: THandle; // handle to group or contact
- ptCursor: TPoint;
- rcItem: TRect;
- end;
-
-const
-
- {
- wParam : 0
- lParam : Pointer to a TCLCINFOTIP structure
- Affect : An InfoTip for an item should be shown now, see notes
- Returns: [non zero] if you process this, because it makes no sense
- for more than one module to process this.
- Notes : It's upto the module where to put the InfoTip, Normally
- it's a few pixels below and to the right of the cursor.
- -
- This event is called after the mouse ehas been stationary over
- a contact for (by default) 200ms
- }
- ME_CLC_SHOWINFOTIP = 'CLC/ShowInfoTip';
-
- {
- wParam : 0
- lParam : Pointer to an initialised TCLCINFOTIP
- Affect : It's time to destroy an infotip, see notes
- Notes : Only cbSize, isGroup, hItem are set
- notes : This is sent when the mouse moves off a contact when ME_CLC_SHOWINFOTIP
- has previously been called.
- -
- If you don't want this behaviour, you should have grabbed the mouse
- capture yourself --
- }
- ME_CLC_HIDEINFOTIP = 'CLC/HideInfoTip';
-
- {
- wParam : new_time
- lParam : 0
- Affect : Set a new hover time before the info tip hooks are called, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : The value of this setting is applid to all current CLC windows
- and saved to b applied to all future windows, it is persistent.
- -
- Time is in milliseconds, default is 750ms
- }
- MS_CLC_SETINFOTIPHOVERTIME = 'CLC/SetInfoTipHoverTime';
-
- {
- wParam : 0
- lParam : 0
- Affect : get the hover time before the infotip hooks are called
- returns: the hover time in MS
- }
- MS_CLC_GETINFOTIPHOVERTIME = 'CLC/GetInfoTipHoverTime';
-
-{$ENDIF}
\ No newline at end of file diff --git a/plugins/ShlExt/inc/m_clist.inc b/plugins/ShlExt/inc/m_clist.inc deleted file mode 100644 index 58f59fac14..0000000000 --- a/plugins/ShlExt/inc/m_clist.inc +++ /dev/null @@ -1,641 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_CLIST}
-{$DEFINE M_CLIST}
-
-{$ifndef STATUSMODES}
- {$include statusmodes.inc}
-{$endif}
-
-const
-
- // for MS_CLIST_GETSTATUSMODEDESCRIPTION
-
- GSMDF_PREFIXONLINE = 1; // prefix "Online :" for online submodes, e.g. 'away'
-
- // for MS_CLIST_ADDMAINMENUITEM
-
- CMIF_GRAYED = 1;
- CMIF_CHECKED = 2;
- CMIF_HIDDEN = 4; // only works on contact menus
- CMIF_NOTOFFLINE = 8; // item won't appear for contacts that are offline
- CMIF_NOTONLINE = 16; // " online
- CMIF_NOTONLIST = 32; // item won't appear on standard contacts
- CMIF_NOTOFFLIST = 64; // item won't appear on contacts that have the 'NotOnList' setting
-
- // for MS_CLIST_MODIFYMENUITEM
-
- CMIM_NAME = $80000000;
- CMIM_FLAGS = $40000000;
- CMIM_ICON = $20000000;
- CMIM_HOTKEY = $10000000;
- CMIM_ALL = $F0000000;
-
- // for MS_CLIST_GETCONTACTDISPLAYNAME
-
- // will never return the user's custom name, even if that's the one to be displayed
- GCDNF_NOMYHANDLE = 1;
-
- // for MS_CLIST_ADDEVENT
-
- //flashes the icon even if the user is occupied, and puts the event
- // at the top of the queue
- CLEF_URGENT = 1;
- { icon will not flash forever, only a few times, e.g. online alert }
- CLEF_ONLYAFEW = 2;
-
- // for MS_CLIST_GETICONSIMAGELIST
-
- IMAGE_GROUPOPEN = 11;
- IMAGE_GROUPSHUT = 12;
-
- // for MS_CLIST_MENUPROCESSCOMMAND
-
- MPCF_CONTACTMENU = 1; // test commands from a contact menu
- MPCF_MAINMENU = 2; // test commands from the main menu
-
- // for MS_CLIST_GROUPGETNAME/2
-
- GROUPF_EXPANDED = $04;
- GROUPF_HIDEOFFLINE = $08;
-
- //
-
- SETTING_TOOLWINDOW_DEFAULT = 1;
- SETTING_SHOWMAINMENU_DEFAULT = 1;
- SETTING_SHOWCAPTION_DEFAULT = 1;
- SETTING_CLIENTDRAG_DEFAULT = 0;
- SETTING_ONTOP_DEFAULT = 1;
- SETTING_MIN2TRAY_DEFAULT = 1;
- SETTING_TRAY1CLICK_DEFAULT = 0;
- SETTING_HIDEOFFLINE_DEFAULT = 0;
- SETTING_HIDEEMPTYGROUPS_DEFAULT = 0;
- SETTING_USEGROUPS_DEFAULT = 1;
- SETTING_SORTBYSTATUS_DEFAULT = 0;
- SETTING_TRANSPARENT_DEFAULT = 0;
- SETTING_ALPHA_DEFAULT = 200;
- SETTING_AUTOALPHA_DEFAULT = 150;
- SETTING_CONFIRMDELETE_DEFAULT = 1;
- SETTING_AUTOHIDE_DEFAULT = 0;
- SETTING_HIDETIME_DEFAULT = 30;
- SETTING_CYCLETIME_DEFAULT = 4;
- SETTING_ALWAYSSTATUS_DEFAULT = 0;
- SETTING_ALWAYSMULTI_DEFAULT = 0;
- SETTING_TRAYICON_SINGLE = 0;
- SETTING_TRAYICON_CYCLE = 1;
- SETTING_TRAYICON_MULTI = 2;
- SETTING_TRAYICON_DEFAULT = SETTING_TRAYICON_SINGLE;
- SETTING_STATE_HIDDEN = 0;
- SETTING_STATE_MINIMIZED = 1;
- SETTING_STATE_NORMAL = 2;
-
-type
-
- PCLISTMENUITEM = ^TCLISTMENUITEM;
- TCLISTMENUITEM = record
- cbSize: int; // size in bytes of this structure
- pszName: PChar; // text of the menu item
- flags: DWORD;
- position: int; // approx position on the menu, lower numbers go nearer the top
- hIcon: THandle; // icon to put by the item, if this was *not* loaded from
- // a resource, you can delete it straight after the call
- pszService: PChar; // name of the service to call when the service is clicked
- pszPopupName: PChar;// name of the popup menu that this item is on, if this
- // is NULL the iteem is on the root of the menu
- popupPosition: int; // position of the popup menu on the root menu, ignored
- // if pszPopupName is NULL(0) or if the popup menu already exists
- hotKey: DWORD; // keyboard accelerator, same as lParam of WM_HOTKEY, 0 for none
- pszContactOwner: PChar; // contact menus only, the protocol module that owns
- // the contacts to which this to which this menu item
- // applies, NULL(0) if it applies to all contacts.
- // if it applies to multiple but not all protocols
- // add multiple menu items or use ME_CLIST_PREBUILDCONTACTMENU
- end;
-
- PCLISTDOUBLECLICKACTION = ^TCLISTDOUBLECLICKACTION;
- TCLISTDOUBLECLICKACTION = record
- cbSize: int;
- pszContactOwner: PChar; // name of the protocol owning the contact or NULL(0) for all
- flags: DWORD; // CMIF_NOT flags above
- pszService: PChar; // service to call on double click, is called with wParam=hContact, lParam=0
- end;
-
- PCLISTEVENT = ^TCLISTEVENT;
- TCLISTEVENT = record
- cbSize: int; // size in bytes
- hContact: THandle; // handle to the contact to put the icon by
- hIcon: THandle; // icon to flash!
- flags: DWORD;
- hDBEvent: THandle; // caller defined, but should be unique for hContact
- lParam: LPARAM;
- pszService: PChar; // name of service to call on activation
- pszTooltip: PChar; // short description of the event to display as a tooltip on the systray
- end;
-
-const
-
- {
- wParam : new_status
- lParam : 0
- Affect : Sent when the user acks to change their status, see notes
- Notes : Also sent due to a MS_CLIST_SETSTATUSMODE
- }
- ME_CLIST_STATUSMODECHANGE = 'CList/StatusModeChange';
-
- {
- wParam : new_status
- lParam : 0
- Affect : Force a change of status mode, see statusmodes.inc
- }
- MS_CLIST_SETSTATUSMODE = 'CList/SetStatusMode';
-
- {
- wParam : 0
- lParam : 0
- Affect : Get the current status mode, see notes
- Notes : This is the status, as set by the user, not any protocol specific status
- all protocol modules will attempt to conform to this setting at ALL times.
- }
- MS_CLIST_GETSTATUSMODE = 'CList/GetStatusMode';
-
- {
- wParam : status_mode
- lParam : flags
- Affect : Get a textual description of the given status mode
- Returns: pointer to a static buffer of the description of the given status mode
- or NULL(0) if the mode was unknown.
- Version: v0.1.0.1+
- }
- MS_CLIST_GETSTATUSMODEDESCRIPTION = 'CList/GetStatusModeDescription';
-
- {
- wParam : 0
- lParam : Pointer to a initalised TCLISTMENUITEM structure
- Affect : Add a new menu item to the main menu, see notes
- Returns: A handle to the new MENU item or NULL(0) on failure
- Notes : The given TCLISTMENUITEM.pszService in is called when the item
- get clicked with :
- -
- wParam = 0, lParam = hwndContactList
- }
- MS_CLIST_ADDMAINMENUITEM = 'CList/AddMainMenuItem';
-
- {
- wParam : 0
- lParam : Pointer to a initalised TCLISTMENUITEM structure
- Affect : Add a new item to the user contact menus, see notes
- Notes : exactly the same as MS_CLIST_ADDMAINMENUITEM except when an item
- is selected, the service gets called with wParam=hContact,
- pszContactOwner is obeyed.
- -
- Popup menus are not supported, pszPopupName and popupPosition
- are ignored. If CTRL is held down when right clicking the menu
- position numbers will be displayed in brackets afterr the menu item
- text, this only works in debug builds!
- }
- MS_CLIST_ADDCONTACTMENUITEM = 'CList/AddContactMenuItem';
-
- {
- wParam : HMENUITEM
- lParam : Pointer to a initalised TCLISTMENUITEM
- Affect : Modify an existing menu item, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : hMenuItem will have been returned by MS_CLIST_ADD[MAIN]MENUITEM
- TCLISTMENUITEM.flags should contain CMIM_* constants (see above)
- to mark which fields should be updated, if it's not present, they
- can't be updated -- if flags do not exist for a field it can not
- be updated.
- Version: v0.1.0.1+
- }
- MS_CLIST_MODIFYMENUITEM = 'CList/ModifyMenuItem';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : the context menu for a contact is about to be built, see notes
- Notes : modules should use this to change menu items that are specific
- to the contact that has them
- Version: v0.1.0.1+
- }
- ME_CLIST_PREBUILDCONTACTMENU = 'CList/PreBuildContactMenu';
-
- {
- wParam : 0
- lParam : Pointer to a initalised TCLISTDOUBLECLICKACTION structure
- Affect : Sets the service to call when a contact is double-clicked, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : in case of conflicts, the first module to have registered
- will get the double click, no others will, this service
- will return success even for duplicates
- -
- This service was dropped from development during 0.3.0.0, it is no
- longer supported, see ME_CLIST_DOUBLECLICKED
- Version: 0.1.2.2+, 0.2.0+ ONLY (not 3.0a)
- }
- MS_CLIST_SETDOUBLECLICKACTION = 'CList/SetDoubleClickAction';
-
- {
- wParam : HCONTACT
- lParam : <none>
- Affect : Register with this event to be notified of a double click on the CList
- against a HCONTACT, you will not be notified if there is a pending CList event
- that the double click clears, (i.e. flashing icon is presented to be clicked)
- Version: 0.3.0.0
- }
- ME_CLIST_DOUBLECLICKED = 'CList/DoubleClicked';
-
- {
- wParam : HCONTACT
- lParam : flags
- Affect : Gets the string that the contact list will use to represent a contact
- Returns: Always a pointer
- Notes : Returns a pointer to the name, will always succeed, even if it needs
- to return "(Unknown Contact)"
- -
- this pointer is a statically allocated buffer which will
- be overwritten on every call to this service, callers should make
- sure that they copy the information before they call it again
- Version: v0.1.2.0+, 0.2.0+ ONLY (0.3a supports the contacts module)
- }
- MS_CLIST_GETCONTACTDISPLAYNAME = 'CList/GetContactDisplayName';
-
- {
- wParam : 0
- lParam : Pointer to a TCLISTEVENT
- Affect : Add's an event to the list
- Notes : The service will flash TCLISTEVENT.hIcon, next to the
- contact, TCLISTEVENT.hContact
- -
- pszService is called is called wParam=hwndContactList,
- lParam=pointer to a TCLISTEVENT.
- -
- the TCLISTEVENT data is invalidated after this service returns
- so copy anything from it if required.
- -
- TCLISTEVENT.pszService will also be called if the user
- double clicks on the icon, at which point it will be removed
- from the contact lists queue automatically.
- -
- TCLISTEVENT.hContact and TCLISTEVENT.hDBEvent should be unique.
- }
- MS_CLIST_ADDEVENT = 'CList/AddEvent';
-
- {
- wParam : HCONTACT
- lParam : HDBEVENT
- Affect : Remove an event from the contact list queue
- Returns: 0 on success, [non zero] on failure
- }
- MS_CLIST_REMOVEEVENT = 'Clist/RemoveEvent';
-
- {
- wParam : HCONTACT
- lParam : iEvent
- Affect : Get the details of an event in the queue, see notes
- Returns: A CLISTEVENT* or NULL(0) on failure
- Notes : Returns the iEvent'1st/2nd/3rd/nth elemented queried,
- e.g. iEvent=0 will get the event that will be returned if the
- user double clicks on that HCONTACT
- -
- Use HCONTACT=NULL, iEvent=0 for example to get the event
- the user will get if they double click on the tray.
- Version: v0.1.2.1+
- }
- MS_CLIST_GETEVENT = 'CList/GetEvent';
-
- {
- wParam : ControlID
- lParam : Pointer to MEASUREITEMSTRUCT struct
- Affect : Process a WM_MEASUREITEM message for user context menus, see notes
- Notes : just because wParam, lParam is defined here, only pass them
- opaquely to this service, as is.
- -
- This is just to draw icons, if it is not called, the icons
- will not be drawn
- Version: v0.1.1.0+
- }
- MS_CLIST_MENUMEASUREITEM = 'CList/MenuMeasureItem';
-
- {
- wParam :
- lParam :
- Affect : Process a WM_DRAWITEM message for user context menus,
- wParam, lParam should be passed from such message handler.
- Version: v0.1.1.0+
- }
- MS_CLIST_MENUDRAWITEM = 'CList/MenuDrawItem';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Built the context menu for a specific contact
- Returns: A HMENU handle identifying the menu, thhis should be DestroyMenu()ed
- when done.
- Version: v0.1.1.0+
- }
- MS_CLIST_MENUBUILDCONTACT = 'CList/MenuBuildContact';
-
- {
- wParam : 0
- lParam : 0
- Affect : Get the image list handle with all the useful icons in it
- Version: v0.1.1.0+
- }
- MS_CLIST_GETICONSIMAGELIST = 'CList/GetIconsImageList';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Get the icon that should be associated with a contact
- Returns: an index into the contact list imagelist, if the icon
- is a flashing icon, this service won't return information about it
- see below
- Version: v0.1.2.0+
- }
- MS_CLIST_GETCONTACTICON = 'CList/GetContactIcon';
-
- {
- wParam : HCONTACT
- lParam : ICON_ID
- Affect : The icon of a contact in the contact list has changed,
- ICON_ID is an index to what image has changed
- Version: v0.1.2.1+
- }
- ME_CLIST_CONTACTICONCHANGED = 'CList/ContactIconChanged';
-
- // ideally only used by a CLIST UI module
-
- {
- wParam : 0
- lParam : 0
- Affect : Get the handle to Miranda's main menu
- Version: v0.1.1.0+
- }
- MS_CLIST_MENUGETMAIN = 'CList/MenuGetMain';
-
- {
- wParam : 0
- lParam : 0
- Affect : Get a handle to Miranda's status menu
- Version: v0.1.1.0+
- }
- MS_CLIST_MENUGETSTATUS = 'CList/MenuGetStatus';
-
- {
- wParam : MAKEWPARAM(LOWORD(wParam of WM_COMMAND),flags)
- lParam : HCONTACT
- Affect : Process a mennu selection from a menu, see notes
- Returns: True if it processed the command, False otherwise
- notes : hContact is the currently selected contact, it is not used
- if this is a main menu command, if this is NULL then the command
- is a contact menu one, the command is ignored
- Version: v0.1.1.0+
- }
- MS_CLIST_MENUPROCESSCOMMAND = 'CList/MenuProcessCommand';
-
- {
- wParam : virtual key code
- lParam : MPCF_* flags
- Affect : Process a menu hotkey, see notes
- Returns: True if it processed the command, False otherwise
- Notes : this should be called in WM_KEYDOWN
- Version: v0.1.1.0+
- }
- MS_CLIST_MENUPROCESSHOTKEY = 'CList/MenuProcessHotkey';
-
- {
- wParam : Pointer to a MSG structurer
- lParam : Pointer to an LRESULT
- Affect : Process all the messages required for docking, see notes
- Returns: True if the message should NOT be processed anymore, False otherwise
- Notes : only msg.hwnd, msg.message, msg.wParam and msg.lParam are used
- your WndProc should return the lResult if AND only IF, TRUE is returned
- Version: v0.1.1.0+
- }
- MS_CLIST_DOCKINGPROCESSMESSAGE = 'CList/DockingProcessMessage';
-
- {
- wParam : 0
- lParam : 0
- Affect : Determines wheter the contact list docked
- Returns: pnon zero] if the contact list is docked, or 0 if it's not
- Version: v0.1.1.0+
- }
- MS_CLIST_DOCKINGISDOCKED = 'CList/DockingIsDocked';
-
- {
- wParam : Pointer to a TMSG
- lParam : Pointer to an LRESULT
- Affect : Process all the messages required for the tray icon, see notes
- Returns: TRUE if the message should not be processed anymore, False otherwise
- Notes : Only msg.hwnd, msg.message, msg.wparam and msg.lParam are used
- your WndProc should return LRESULT if and ONLY if TRUE is returned
- Version: v0.1.1.0+
- }
- MS_CLIST_TRAYICONPROCESSMESSAGE = 'CList/TrayIconProcessMessage';
-
- {
- wParam : Pointer to TMSG
- lParam : Pointer to an LRESULT
- Affect : Process all the messages required for hotkeys, see notes
- Returns: True if the message should not be processed anymore or False otherwise
- Notes : only msg.hwnd, msg.message, msg.wParam, msg.lParam are used
- Version: v0.1.1.0+
- }
- MS_CLIST_HOTKEYSPROCESSMESSAGE = 'CList/HotkeysProcessMessage';
-
- {
- wParam : 0
- lParam : 0
- Affect : Toggles the show/hide status of the contact list
- Returns: 0 on success, [non zero] on failure
- Version: v0.1.1.0+
- }
- MS_CLIST_SHOWHIDE = 'CList/ShowHide';
-
- {
- wParam : 0
- lParam : 0
- Affect : temporarily disable the autohide feature, see notes
- Notes : this service will restart the auto hide timer, so if you need
- to keep the window visible you'll have to bee getting user input
- or calling this service each time
- Version: v0.1.2.1+
- }
- MS_CLIST_PAUSEAUTOHIDE = 'CList/PauseAutoHide';
-
- {
- wParam : HPARENTGROUP
- lParam : 0
- Affect : Create a new group and calls CLUI to display it, see notes
- Returns: A handle to the new group.
- Notes : If HPARENTGROUP is NULL(0) it will create a group at the root.
- Version: v0.1.1.0+
- }
- MS_CLIST_GROUPCREATE = 'CList/GroupCreate';
-
- {
- wParam : HGROUP
- lParam : 0
- Affect : Delete a group and call CLUI to display the change
- Returns: 0 on success, [non zero] on failure
- Version: v0.1.1.0+
- }
- MS_CLIST_GROUPDELETE = 'CList/GroupDelete';
-
- {
- wParam : HGROUP
- lParam : newState
- Affect : Change the expanded state flag for a group internally, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : if newState is non zero then the group is expanded, 0 it's collapsed
- CLUI IS *NOT* called when the change is made.
- Version: v0.1.1.0+
- }
- MS_CLIST_GROUPSETEXPANDED = 'CList/GroupSetExpanded';
-
- {
- wParam : HGROUP
- lParam : MAKELPARAM(flags, flagsMask)
- Affect : Change the flag for a group, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : only if flags given in flagsmask are altered,
- CLUI is called on change to GROUPF_HIDEOFFLINE
- Version: v0.1.2.1+
- }
- MS_CLIST_GROUPSETFLAGS = 'CList/GroupSetFlags';
-
- {
- wParam : HGROUP
- lParam : Pointer to a integer to be filled with expanded state
- Affect : get the name of a group, see notes
- Returns: a static buffer pointing to the name of the group
- returns NULL(0) if HGROUP is invalid.
- Notes : the returned buffer is only valid til the next call
- to this service, lParam can be NULL(0) if you don't
- want to know if the group is expanded
- Version: v0.1.1.0+
- }
- MS_CLIST_GROUPGETNAME = 'CList/GroupGetName';
-
- {
- wParam : HGROUP
- lParam : Pointer to flags
- Affect : Get the name of the group, see notes
- Returns: A static buffer pointing to the name of the group
- returns NULL(0) if HGROUP is invalid
- Note : this buffer is only valid til the next call to this service
- flags can be NULL(0), otherwise it'll return GROUPF_* constants
- Version: v0.1.2.1+
- }
- MS_CLIST_GROUPGETNAME2 = 'CList/GroupGetName2';
-
- {
- wParam : HGROUP
- lParam : HBEFOREGROUP
- Affect : Move a group directly before another group
- Returns: the new handle of the group on success, NULL(0) on failure
- Notes : the order is represented by the order in which MS_CLUI_GROUPADDED
- is called, however UI's are free to ignore this order and sort
- if they wish.
- Version: v0.1.2.1+
- }
- MS_CLIST_GROUPMOVEBEFORE = 'CList/GroupMoveBefore';
-
- {
- wParam : HGROUP
- lParam : Pointer to a null terminated string containing the new name
- Affect : Rename a group internally, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : this will fail if the group name is a duplicate of an existing
- a name, CLUI is not called when this change is made.
- Version: v0.1.1.0+
- }
- MS_CLIST_GROUPRENAME = 'CList/GroupRename';
-
- {
- wParam : 0
- lParam : 0
- Affect : Build a menu of the group tree, see notes
- Returns: Handle to the menu, NULL(0) on failure
- Notes : NULL be returned if the user doesn't have any groups
- the dwItemData of every menu item is the handle to that group.
- Menu item ID's are assigned starting at 100 in no particular order
- Version: v0.1.2.1+
- }
- MS_CLIST_GROUPBUILDMENU = 'CList/GroupBuildMenu';
-
- {
- wParam : newValue
- lParam : 0
- Affect : Changes the 'hide offline contacts' flag and calls CLUI, see notes
- Returns: 0 success, [non zero] on failure
- Notes : newValue is 0 to show all contacts, 1 to show only online contacts
- -1 to toggle the value
- Version: v0.1.1.0+
- }
- MS_CLIST_SETHIDEOFFLINE = 'CList/SetHideOffline';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Do the message processing associated with the double clicking a contact
- Returns: 0 on success, [non zero] on failure
- Version: v0.1.1.0+
- }
- MS_CLIST_CONTACTDOUBLECLICKED = 'CList/ContactDoubleClicked';
-
- {
- wParam : HCONTACT
- lParam : Pointer to an array of pchar's containing files/dirs
- Affect : Do the processing when some files are droppeed on a contact, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : the array is terminated when a NULL(0) entry is found
- Version: v0.1.2.1+
- }
- MS_CLIST_CONTACTFILESDROPPED = 'CList/ContactFilesDropped';
-
- {
- wParam : HCONTACT
- lParam : HGROUP
- Affect : Change the group a contact belongs to, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : use hGroup=NULL(0) to remove any group association with the contact
- Version: v0.1.1.0+
- }
- MS_CLIST_CONTACTCHANGEGROUP = 'CList/ContactChangeGroup';
-
- {
- wParam : HCONTACT_1
- lParam : HCONTACT_2
- Affect : Determine the ordering of two given contacts
- Returns: 0 if hContact1 is the same as hContact2
- 1 if hContact1 should be displayed before hContact2
- -1 if hContact1 should be displayed after hCotnact2
- Version: v0.1.1.0+
- }
- MS_CLIST_CONTACTSCOMPARE = 'CList/ContactsCompare';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_clui.inc b/plugins/ShlExt/inc/m_clui.inc deleted file mode 100644 index 09f2b999a3..0000000000 --- a/plugins/ShlExt/inc/m_clui.inc +++ /dev/null @@ -1,215 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_CLUI}
-{$DEFINE M_CLUI}
-
- {<</
- this header was created for use for v0.1.1.0, most of it's UI related
- stuff and you probably don't need to call it, see m_clist.inc instead.
- -- There are some functions that were implemented in v0.1.2.0 though
- />>}
-
-const
-
- {
- wParam : 0
- lParam : 0
- Affects: Returns a window handle for the contact list window, see notes
- Returns: ""
- Notes : This call has a very specific purpose internally Miranda
- and shouldn't be used gratuitously, in almost all cases
- there's another call to do whatever it is that you're
- trying to do.
- }
- MS_CLUI_GETHWND = 'CLUI/GetHwnd';
-
- {
- wParam : new status
- lParam : null terminated string to a protocol ID
- Affects: Change the protocol specific status indicators, see notes!
- Returns: 0 on success, [non zero] on failure
- Notes : protocol modules don't want to call this, they want
- clist/protocolstatuschanged instead
- }
- MS_CLUI_PROTOCOLSTATUSCHANGED = 'CLUI/ProtocolStatusChanged';
-
- {
- wParam : Handle to a group
- lParam : 1 or 0
- Affect : A new group was created, add it to the list, see notes
- Notes : lParam is set to 1 or 0 if the user just created
- the group or not.
- -
- this is also called when the contact list is being rebuilt,
- new groups are always created with the name 'New group'
- }
- MS_CLUI_GROUPADDED = 'CLUI/GroupCreated';
-
- {
- wParam : HCONTACT
- lParam : ICON_ID
- Affect : Change the icon for a contact, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : ICON_ID is an offset in the imagelist, see clist/geticonsimagelist
- }
- MS_CLUI_CONTACTSETICON = 'CLUI/ContactSetIcon';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Remove a contact from the list, see notes
- Returns: 0 on success, [non zereo] on failure
- Notes : this contact is NOT actually being deleted, since if
- a contact goes offline while 'hide offline' option is sset,
- this service will be called then ALSO
- }
- MS_CLUI_CONTACTDELETED = 'CLUI/ContactDeleted';
-
- {
- wParam : HCONTACT
- lParam : ICON_ID
- Affect : Add a contact to the list, see note
- returns: 0 on success, [non zero] on failure
- Notes : the caller processes the 'hide offline' setting, so the callee
- should not do further processing based on the value of this setting
- -
- WARNING: this will be called to re-add a contact when they come
- online if 'hide offline' is on, but it cannot determine if
- the contact is already on the list, so you may get requests to
- add a contact when it is already on the list, which you should ignore.
- -
- You'll also get this whenever an event is added for a contact,
- since if the contact was offline, it needs to be shown to
- display the mesage, even if 'hide offlines' is on.
- -
- you should not resort the list on this call, a seperate resort
- request will be sent.
- -
- ICON_ID is an offset in the image list, see clist/geticonsimagelist
-
- }
- MS_CLUI_CONTACTADDED = 'CLUI/ContactAdded';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Reename a contact in the lists, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : You should not re-sort the list on this call, a separate resort
- request will be sent, you can get the new name from clist/getcontactdisplayname
- }
- MS_CLUI_CONTACTRENAMED = 'CLUI/ContactRenamed';
-
- {
- wParam : 0
- lParam : 0
- Affect : Start a rebuild of the contact list, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : this is the cue to clear the existing content of the list
- expect to get a series of :
-
- clui/groupadded
- clui/contactadded
- clui/resortlist
- }
- MS_CLUI_LISTBEGINREBUILD = 'CLUI/ListBeginRebuild';
-
- {
- wParam : 0
- lParam : 0
- Affect : End a rebuild of the contact list, see notes
- Returns: 0 on success, [non zero] on error
- Notes : if you dissplayed an hourglass in beginbuild, set it back
- here, you do not need to explicitly sort the list
- }
- MS_CLUI_LISTENDREBUILD = 'CLUI/ListEndRebuild';
-
- {
- wParam : 0
- lParam : 0
- Affect : Sort the contact list now, see notes
- Returns: 0 success, [non zero] on failure
- Notes : Sorts are buffered so you won't get this message lots of times
- if the lists needs to be resorted many times rapidly
- }
- MS_CLUI_SORTLIST = 'CLUI/SortList';
-
- {
- wParam : CLUICAPS_*
- lParam : 0
- Affect : Gets a load of capabilites for the loaded CLUI, see notes
- Returns: the requested value, 0 of wParam is unknown --
- if this service is not implemented it is assumed all return
- values will be 0.
- Version: v0.1.2.1+
- }
-
- { can only provide this flag to return the following set of caps, the strings
- show the database setting/type to store the list option, changing the value
- does not reflect what the change is, i.e. ontop can only be affected with
- a call to SetWindowPos() }
- CLUICAPS_FLAGS1 = 0;
- { empty groups aren't shown, 'CList/HideEmptyGroups' (byte) [changes make the list reload] }
- CLUIF_HIDEEMPTYGROUPS = 1;
- { groups can be disabled, lists can be merged into one seamlessly, (byte) 'CList/UseGroups' }
- CLUIF_DISABLEGROUPS = 2;
- { list can be displayed 'on top' of all other windows, 4 (byte) 'CList/OnTop' }
- CLUIF_HASONTOPOPTION = 4;
- { can disappear after a while of inactive use,
- (byte) 'CList/AutoHide' (word) 'CList/HideTime' }
- CLUIF_HASAUTOHIDEOPTION = 8;
-
- MS_CLUI_GETCAPS = 'CLUI/GetCaps';
-
- {
- wParam : HCONTACT
- lParam : MAKELPARAM(screenX, screenY)
- Affect : A contact is being dragged outside the main window
- Return : return [non zero] to show the drag cursor as "accepting" the drag
- or zero to show the circle/slash 'not allowed'
- Version: v0.1.2.0+
- }
- ME_CLUI_CONTACTDRAGGING = 'CLUI/ContactDragging';
-
- {
- wParam : HCONTACT
- lParam : MAKELPARAM(screenX, screenY)
- Affect : a contact has just been dropped outside the main window, see notes
- Notes : return non zero to stop other hooks processing this event.
- Version: v0.1.2.0+
- }
- ME_CLUI_CONTACTDROPPED = 'CLUI/ContactDropped';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : A contact that *was* being dragged outside the main window
- has gone back to the main window
- Return : always return 0
- Version: v0.1.2.1+
- }
- ME_CLUI_CONTACTDRAGSTOP = 'CLUI/ContactDragStop';
-
-{$ENDIF}
\ No newline at end of file diff --git a/plugins/ShlExt/inc/m_contacts.inc b/plugins/ShlExt/inc/m_contacts.inc deleted file mode 100644 index 7ba6f68bbb..0000000000 --- a/plugins/ShlExt/inc/m_contacts.inc +++ /dev/null @@ -1,90 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-type
-
- PCONTACTINFO = ^TCONTACTINFO;
- TCONTACTINFO = record
- cbSize: int;
- dwFlag: Byte;
- hContact: THandle;
- szProto: PChar;
- type_: Byte;
- retval: record (* in C this is a nameless union *)
- case longint of
- 0: (bVal: Byte);
- 1: (wVal: WORD);
- 2: (dVal: DWORD);
- 3: (pszVal: PChar);
- 4: (cchVal: Word);
- end;
- end;
-
-const
-
-// CNF_* Types of information you can retreive by setting the dwFlag in CONTACTINFO
-
- CNF_FIRSTNAME = 1; // returns first name (string)
- CNF_LASTNAME = 2; // returns last name (string)
- CNF_NICK = 3; // returns nick name (string)
- CNF_CUSTOMNICK = 4; // returns custom nick name, clist name (string)
- CNF_EMAIL = 5; // returns email (string)
- CNF_CITY = 6; // returns city (string)
- CNF_STATE = 7; // returns state (string)
- CNF_COUNTRY = 8; // returns country (string)
- CNF_PHONE = 9; // returns phone (string)
- CNF_HOMEPAGE = 10; // returns homepage (string)
- CNF_ABOUT = 11; // returns about info (string)
- CNF_GENDER = 12; // returns gender (byte,'M','F' character)
- CNF_AGE = 13; // returns age (byte, 0==unspecified)
- CNF_FIRSTLAST = 14; // returns first name + last name (string)
- CNF_UNIQUEID = 15; // returns uniqueid, protocol username (must check type for type of return)
-
-// Special types
-// Return the custom name using the name order setting
-// IMPORTANT: When using CNF_DISPLAY you MUST free the string returned
-// You must **NOT** do this from your version of free() you have to use Miranda's free()
-// you can get a function pointer to Miranda's free() via MS_SYSTEM_GET_MMI, see m_system.h
- CNF_DISPLAY = 16;
-// Same as CNF_DISPLAY except the custom handle is not used
-// IMPORTANT: When using CNF_DISPLAYNC you MUST free the string returned
-// You must **NOT** do this from your version of free() you have to use Miranda's free()
-// you can get a function pointer to Miranda's free() via MS_SYSTEM_GET_MMI, see m_system.h
- CNF_DISPLAYNC = 17;
-
-// If MS_CONTACT_GETCONTACTINFO returns 0 (valid), then one of the following
-// types is setting telling you what type of info you received
- CNFT_BYTE = 1;
- CNFT_WORD = 2;
- CNFT_DWORD = 3;
- CNFT_ASCIIZ = 4;
-
- {
- wParam : not used
- lParam : Pointer to an initialised TCONTACTINFO structure
- affects: Get contact information
- returns: Zero on success, non zero on failure.
- notes : If successful, the type is set and the result is put into the associated member of TCONTACTINFO
- }
- MS_CONTACT_GETCONTACTINFO = 'Miranda/Contact/GetContactInfo';
diff --git a/plugins/ShlExt/inc/m_database.inc b/plugins/ShlExt/inc/m_database.inc deleted file mode 100644 index f2b26508df..0000000000 --- a/plugins/ShlExt/inc/m_database.inc +++ /dev/null @@ -1,654 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_DATABASE}
-{$DEFINE M_DATABASE}
-
-const
-
- DBVT_DELETED = 0; // setting got deleted, no values are valid
- DBVT_BYTE = 1; // bVal, cVal are valid
- DBVT_WORD = 2; // wVal, sVal are valid
- DBVT_DWORD = 4; // dVal, lVal are valid
- DBVT_ASCIIZ = 255; // pszVal is valid
- DBVT_BLOB = 254; // cpbVal and pbVal are valid
- DBVTF_VARIABLELENGTH = $80; // ?
-
-type
-
- HCONTACT = Integer;
- HDBEVENT = Integer;
-
- PDBVARIANT = ^TDBVARIANT;
- TDBVARIANT = record
- type_: Byte;
- case LongInt of
- 0: (bVal: Byte);
- 1: (cVal: Char);
- 2: (wVal: Word);
- 3: (sVal: SmallInt);
- 4: (dVal: LongInt);
- 5: (lVal: Integer);
- 6: (
- pszVal: PChar;
- cchVal: Word;
- );
- 7: (
- cpbVal: Word;
- pbVal: PByte;
- );
- end;
-
-const
-
- {
- wParam : size of the buffer to be filled
- lParam : pointer to the buffer to be filled
- affect : Get's the name of the current profile being used by the database
- module -- this is the same as the filename of the profile without
- the .ext
- return : 0 on success, non zero on failure
- }
- MS_DB_GETPROFILENAME = 'DB/GetProfileName';
-
- {
- wParam : size of buffer pointed to by lParam
- lParam : pointer to a buffer to be filled
- affect : Fill a buffer with the current profile path being used, this does not include the trailing backslash.
- return : 0 on success, non zero on failure
- version: 0.3a only
- }
- MS_DB_GETPROFILEPATH = 'DB/GetProfilePath';
-
-type
-
- PDBCONTACTGETSETTING = ^TDBCONTACTGETSETTING;
- TDBCONTACTGETSETTING = record
- { name of the module that wrote the setting to get }
- szModule: PChar;
- { the name of the setting to get }
- szSetting: PChar;
- { pointer to DBVARIANT to receive the value -- must be allocated for GETSETTINGSTATIC
- calls thou }
- pValue: PDBVARIANT;
- end;
-
- PDBCONTACTWRITESETTING = ^TDBCONTACTWRITESETTING;
- TDBCONTACTWRITESETTING = record
- { module sig to write this setting under }
- szModule: PChar;
- { setting name to write }
- szSetting: PChar;
- { variant containing value to set }
- value: TDBVARIANT;
- end;
-
-const
-
- {
- wParam : Handle of a contact to get the setting for (see notes)
- lParam : pointer to a TDBCONTACTGETSETTING structure to be filled with setting
- this structure also has to be initalised (see notes)
- affect : Queries the database module for a setting from a contact.
- returns: 0 on success, non zero on failure (contact not found, setting doesn't exist)
- notes : TDBCONTACTGETSETTING must be filled with the module name that created
- /wrote the setting you want to get (e.g. your module name)
- and the actual setting to read with TDBCONTACTGETSETTING.szModule and
- TDBCONTACTGETSETTING.szSetting -- TDBCONTACTGETSETTING.pValue is
- a pointer to a TDBVARIANT with the returned setting, this maybe nil
- and MUST be freed after you're done with it with FreeVariant()
-
- There are helper functions for reading/writing/deleting common types to and
- from the database -- see DBGetContactSetting<type>
-
- the contact handle (hContact) can be returned by FindContact/AddContact
- }
- MS_DB_CONTACT_GETSETTING = 'DB/Contact/GetSetting';
-
- {
- wParam : Handle for a contact to query a setting for
- lParam : Pointer to a TDBCONTACTGETSETTING structure
- affects: This service is almost the same as the one above, but it does
- not return a dynamic copy (with malloc()) -- the caller
- must do this for datatypes which require it, e.g. a string.
-
- This means the TDBCONTACTGETSETTING.pValue *has* to exist and be
- allocated by the caller (doesn't have to be allocated from the heap)
- the DBVARIANT structure has to be initalised with the type wanted
- and enough buffer space around to return the info, do not
- expect this service to be as fast as the one above.
-
- returns: 0 on success, non zero on failure.
- }
- MS_DB_CONTACT_GETSETTINGSTATIC = 'DB/Contact/GetSettingStatic';
-
- {
- wParam : 0
- lParam : Pointer to a TDBVARIANT structure
- affect : Free's the passed DBVARIANT's dynamic memory (if any) see notes
- returns: 0 on success, non zero on failure
- notes : use the helper function FreeVariant()
- }
- MS_DB_CONTACT_FREEVARIANT = 'DB/Contact/FreeVariant';
-
- {
- wParam : Handle to contact to write setting for
- lParam : Pointer to TDBCONTACTWRITESETTING which must be initalised
- affects: writes a setting under a contact -- TDBCONTACTWRITESETTING structure
- must contain the module name writing -- the setting name, and the value
- to write (which is NOT a pointer) .szModule, .szSetting, .Value, see notes
- returns: 0 on success, non zero on failure
- notes : this service triggers 'DB/Contact/SettingChanged' before it returns
- as always, there is a helper function to use this service.
- }
- MS_DB_CONTACT_WRITESETTING = 'DB/Contact/WriteSetting';
-
- {
- wParam : hContact under which the setting should be deleted
- lParam : Pointer to a TDBCONTACTGETSETTING structure
- affects: Deletes the given setting for a contact, the TDBCONTACTGETSETTING.pValue
- field is ignored -- only .szModule and .szSetting are needed, see notes
- returns: 0 on success, non zero on failure
- notes : triggers 'DB/Contact/SettingChanged' BEFORE it deletes the given
- setting, when the service returns the TDBVARIANT structure .type_ is set
- to 0 and no fields are valid, there is a helper function for this
- service, see below.
- }
- MS_DB_CONTACT_DELETESETTING = 'DB/Contact/DeleteSetting';
-
- {
- wParam : Handle of a contact to enum settings for
- lParam : Pointer to a TDBCONTACTENUMSETTINGS structure, must be initalised
- affect : Enumerates all settings for a given contact under a module,
- TDBCONTACTENUMSETTINGS must be filled with the function pointer to call
- the TDBCONTACTENUMSETTINGS.lParam value to pass to it each time,
- as well as the .szModule under which the contact is valid
- returns: returns the value of the last call to the enum function, or -1
- if no settings could be enumerated
- notes : the szSetting argument passed to the enumeration function is only
- valid for the duration of that enumeration call,
- it must be allocated dynamically if it is required after that call frame
- has returned.
- Also, deleting settings as they are enumerated has unpredictable results!
- but writing a new value for a setting is okay.
- it is unclear how you stop the enumeration once it is started, maybe
- possible to return -1 to stop it.
- vesion : only valid for 0.1.0.1+
- }
-
-type
-
- TDBSETTINGENUMPROC = function(const szSetting: PChar; lParam: LPARAM): int; cdecl;
-
- PDBCONTACTENUMSETTINGS = ^TDBCONTACTENUMSETTINGS;
- TDBCONTACTENUMSETTINGS = record
- { function pointer to call to start the enum via MS_DB_CONTACT_ENUMSETTINGS }
- pfnEnumProc: TDBSETTINGENUMPROC;
- { passed to the above function }
- lParam: LPARAM;
- { name of the module to get settings for }
- szModule: PChar;
- { not used by us }
- ofsSettings: DWORD;
- end;
-
-const
-
- MS_DB_CONTACT_ENUMSETTINGS = 'DB/Contact/EnumSettings';
-
- {
- wParam : 0
- lParam : 0
- affect : none
- returns: Returns the number of contacts in the database for the loaded profile
- not including the profile user, see notes.
- notes : the contacts in the database can be read with FindFirst/FindNext
- }
- MS_DB_CONTACT_GETCOUNT = 'DB/Contact/GetCount';
-
- {
- wParam : 0
- lParam : 0
- returns: Returns a handle to the first contact in the database,
- this handle does not need to be closed, if there are no users
- NULL(0) is returned.
- }
- MS_DB_CONTACT_FINDFIRST = 'DB/Contact/FindFirst';
-
- {
- wParam : Contact handle
- lParam : 0
- returns: Returns a handle to the next contact after the given contact in
- wParam, this handle does not neeed to be closed -- may return NULL(0)
- if the given contact in wParam was the last in the database, or the
- given contact was invalid
- }
- MS_DB_CONTACT_FINDNEXT = 'DB/Contact/FindNext';
-
- {
- wParam : Handle of a contact to delete
- lParam : 0
- affect : the user by the given handle is deleted from the database, see notes
- returns: Returns 0 on success or nonzero if the handle was invalid
- notes : this triggers DB/Contact/Deleted BEFORE it actually deletes the contact
- all events are also deleted -- other modules may end up with invalid
- handles because of this, which they should be prepared for.
- }
- MS_DB_CONTACT_DELETE = 'DB/Contact/Delete';
-
- {
- wParam : 0
- lParam : 0
- affects: creates a new contact in the database, they have no settings,
- settings must be added with MS_DB_CONTACT_WRITESETTING or
- database helper functions for writing, see notes
- returns: A handle to a new contact or NULL(0) on failure.
- notes : triggers the ME_DB_CONTACT_ADDED event just before the service returns
- }
- MS_DB_CONTACT_ADD = 'DB/Contact/Add';
-
-
- {
- wParam : (HANDLE) hContact
- lParam : 0
- affects: Checks the given handle within the database for valid information, for
- a proper internal header.
- returns: Returns 1 if the contact handle is valid, 0 if it is not
- notes : Due to the nature of multiple threading a contact handle can be deleted
- soon after this service has returned a handle as valid, however it will never point
- to another contact.
- }
- MS_DB_CONTACT_IS = 'DB/Contact/Is';
-
-
- {
- wParam : contact handle for events count is needed
- lParam : 0
- service: Gets the number of events in the chain belonging to a contact
- in the databasee.
- returns: the numbef of events owned by hContact or -1 if hContact
- is invalid, they can be found with the event/find* servicees
- }
- MS_DB_EVENT_GETCOUNT = 'DB/Event/GetCount';
-
- {
- wParam : contact handle to add an event for
- lParam : Pointer to TDBEVENTINFO initialised with data
- affect : Add's an event to the contact's event list, the TDBEVENTINFO
- structure should be filled with the event of message -- see notes
- returns: a handle to a DB event (HDBEVENT), or NULL on error
- notes : Triggers DB/Event/Added event just before it returns,
- Events are sorted chronologically as they are entered,
- so you cannot guarantee that the new hEvent is the last event in the chain,
- however if a new event is added that has a timestamp less than
- 90 seconds *before* the event that should be after it,
- it will be added afterwards, to allow for protocols that only
- store times to the nearest minute, and slight delays in transports.
- There are a few predefined eventTypes below for easier compatibility, but
- modules are free to define their own, beginning at 2000
- DBEVENTINFO.timestamp is in GMT, as returned by time()
- }
-
- DBEF_FIRST = 1; // internally only, do not use
- DBEF_SENT = 2; // if set, the event was sent by the user, otherwise it was received
- DBEF_READ = 4; // event has been read by the user -- only needed for history
-
- EVENTTYPE_MESSAGE = 0;
- EVENTTYPE_URL = 1;
- EVENTTYPE_CONTACTS = 2; // v0.1.2.2+
- EVENTTYPE_ADDED = 1000; // v0.1.1.0+: these used to be module-
- EVENTTYPE_AUTHREQUEST = 1001; // specific codes, hence the module-
- EVENTTYPE_FILE = 1002; // specific limit has been raised to 2000
-
-type
-
- PDBEVENTINFO = ^TDBEVENTINFO;
- TDBEVENTINFO = record
- { size of the structure }
- cbSize: int;
- { module that 'owns' this event and controls the data format }
- szModule: PChar;
- { timestamp in UNIX time }
- timestamp: DWORD;
- { the DBEF_* flags above }
- flags: DWORD;
- { event type, such as message, can be module defined }
- eventType: WORD;
- { size in bytes of pBlob^ }
- cbBlob: DWORD;
- { pointer to buffer containing the module defined event data }
- pBlob: PByte;
- end;
-
-const
-
- MS_DB_EVENT_ADD = 'DB/Event/Add';
-
-
-
- {
- wParam : Handle to the contact
- lParam : HDBEVENT handle to delete
- affects: Removes a single event from the database for the given contact
- returns: 0 on success, nonzero on failure
- notes : Triggers DB/Event/Deleted just before the event *is* deleted
- }
- MS_DB_EVENT_DELETE = 'DB/Event/Delete';
-
- {
- wParam : Handle to DB event
- lParam : 0
- returns: Returns the space in bytes requried to store the blob in HDBEVENT
- given by HDBEVENT(wParam) -- or -1 on error
- }
- MS_DB_EVENT_GETBLOBSIZE = 'DB/Event/GetBlobSize';
-
- {
- wParam : Handle to a DB event
- lParam : Pointer to a TDBEVENTINFO structure which must be initialised
- affects: Returns all the information about an DB event handle to a TDBEVENTINFO
- structure which must be initalised, DBEI.cbSize, DBEI.pBlob and DBEI.cbSize
- before calling this service, the size can be assertained with
- GetBlobSize() service, see notes
- returns: Returns 0 on success, non zero on failure
- notes : 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.
- }
- MS_DB_EVENT_GET = 'DB/Event/Get';
-
- {
- wParam : HCONTACT
- lParam : HDBEVENT
- affect : Changes the flag for an event to mark it as read
- Returns: Returns the entire flag DWORD for the event after the change, or -1
- if HDBEVENT is invalid, see notes
- notes : This iss one of the database write operations that does not trigger
- an event, modules should not save flagss states for any length of time.
- }
- MS_DB_EVENT_MARKREAD = 'DB/Event/MarkRead';
-
- {
- wParam : HDBEVENT
- lParam : 0
- Affect : Returns a handle to a contact that owns the HDBEVENT,
- see notes
- Returns: Returns a handle if successful or HDBEEVENT(-1) on failure
- notes : This service is very slow, only use wheen you have no other choice
- at all.
- }
- MS_DB_EVENT_GETCONTACT = 'DB/Event/GetContact';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Retrieves a handlee to the first event in the chain
- for a HCONTACT
- returns: Returns a handle, or NULL(0) if HCONTACT is invalid or has
- no events, events in a chain are sorted chronologically automatically
- }
- MS_DB_EVENT_FINDFIRST = 'DB/Event/FindFirst';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Retrieves a handle to the first unreead event in a chain for a HCONTACT
- see notes
- Returns: Returns a HDBEVENT handle or NULL(0) if the HCONTACT is invalid
- or all it's events have beeen read.
- Notes : Events in a chain are sorted chronologically automatically,
- but this does not necessarily mean that all events after
- the first unread are unread too.
- They should be checked individually with event/findnext and event/get
- This service is designed for startup, reloading all the events that remained
- unread from last time
- }
- MS_DB_EVENT_FINDFIRSTUNREAD = 'DB/Event/FindFirstUnread';
-
- {
- wParam : HCONTACT
- lParam : 0;
- Affects: Retrieves a handle to the lasts event in the chain for a HCONTACT
- Returns: Returns a handle or NULL(0) if HCONTACT is invalid or has no events
- }
- MS_DB_EVENT_FINDLAST = 'DB/Event/FindLast';
-
- {
- wParam : HDBEVENT
- lParam : 0
- Affects: Retrieves a handle to the next event in a chain after HDBEVENT
- Returns: A handle to the next DB event or NULL(0) if HDBEVENT is invalid
- or the last event in the chain.
- }
- MS_DB_EVENT_FINDNEXT = 'DB/Event/FindNext';
-
- {
- wParam : HDBEVENT
- lParam : 0
- Affects: Retrieves a handle to the previous event in a chain before HDBEVENT
- Returns: A handle to the previous HDBEVENT or NULL(0) if HDBEVENT is invalid
- or is the first event in the chain
- }
- MS_DB_EVENT_FINDPREV = 'DB/Event/FindPrev';
-
-
-
- {
- wParam : size in bytes of string buffer (including null term)
- lParam : pointer to string buffer
- Affect : Scrambles the string buffer in place using a strange encryption algorithm,
- see notes
- Returns: Always returns 0
- notes : this service may be changed at a later date such that it increasess
- the length of the string
- }
- MS_DB_CRYPT_ENCODESTRING = 'DB/Crypt/EncodeString';
-
- {
- wParam : size in bytes of string buffer, including null term
- lParam : pointer to string buffer
- Affect : Descrambles pszString in-place using the strange encryption algorithm,
- see notes.
- Return : Always returns 0
- notes : Reverses the operation done by MS_DB_CRYPT_ENCODINGSTRING
- }
- MS_DB_CRYPT_DECODESTRING = 'DB/Crypt/DecodeString';
-
-
-
- {
- wParam : timestamp (DWORD)
- lParam : 0
- Affect : Converts a GMT timestap into local time
- Returns: Returns the converted value, see notes
- Notes : Timestamps have a zereo at midnight 1/1/1970 GMT, this service
- converts such a value to be based at midnight 1/1/1970 local time.
- This service does not use a simple conversion based on the current offset
- between GMT and local. Rather, it figures out whether daylight savings time
- would have been in place at the time of the stamp and gives the local time as
- it would have been at the time and date the stamp contains.
- }
- MS_DB_TIME_TIMESTAMPTOLOCAL = 'DB/Time/TimestampToLocal';
-
- {
- wParam : timestamp (DWORD)
- lParam : pointer to initalised DBTIMETOSTRING structure
- Affect : Converts a GMT timestamp to a customisable local time string
- see notes
- Returns: Always returns 0
- notes : The string is formatted according to thhe current user's locale
- language and preference --
-
- .szFormat can have the following special chars :
- t time without seconds, e.g. hh:mm
- s time with seconds, e.g. hh:mm:ss
- m time without minutes e.g. hh
- d short date, e.g. dd/mm/yyyy
- D long date, e.g. d mmmm yyyy
-
- all other characters are copied as is.
- }
-
-type
-
- PDBTIMETOSTRING = ^TDBTIMETOSTRING;
- TDBTIMETOSTRING = record
- { format string, see above }
- szFormat: PChar;
- { pointer to dest buffer to store the result }
- szDest: PChar;
- { size of the buffer }
- cbDest: int;
- end;
-
-const
-
- MS_DB_TIME_TIMESTAMPTOSTRING = 'DB/Time/TimestampToString';
-
-
-
- {
- wParam : newSetting (BOOLEAN)
- lParam : 0
- Affect : Miranda's database is normally protected against corruption by
- aggressively flushing data to the disk on writes, if you're doing
- alot of writes e.g. an import plugin, it can sometimes be desirable
- to switch this feature off to speed up the process, if you do switch
- it off, you must remember that crashes are far more likely to be
- catastrophic, so switch it back on at the earliest possible opportunity.
- if you're doing a lot of setting writes, the flush is already delayed
- so you need not use this service for that purpose, see notes.
- Returns: Always returns 0 (successful)
- notes : This is set to true initally
- }
- MS_DB_SETSAFETYMODE = 'DB/SetSafetyMode';
-
- {
- wParam : (caller defined data) will be passed to lParam of the call back
- lParam : function pointer to TDBMODULEENUMPROC
- Affects: Enumerates the names of all modules that have stored or
- requested information from the database,
- the modules are returned in no real order --
- Writing to the database while module names are being enumerated will cause
- unpredictable results in the enumeration, but the write will work.
-
- the enumeration will stop if the callback returns a non zero value.
-
- Returns: the last return value from the enumeration call back.
- Notes : This service is only useful for debugging or EnumSettings
- version: The service registered to enumerate all modules that have touched
- the database module uses wParam as the lParam cookie value and the lParam
- value given here is the function pointer -- this is not safe
- to use before v0.1.2.1 because I don't know if this was done in v0.1.2.1-
-
- prior to v0.1.2.1 you can not pass a value to the enumeration because
- of a bug -- which is fixed, but hey :) -- [sam]
- }
-type
- TDBMODULEENUMPROC = function(const szModule: PChar; ofsModuleName: DWORD; lParam: LPARAM): int; cdecl;
-const
- MS_DB_MODULES_ENUM = 'DB/Modules/Enum';
-
-
-
- {
- wParam : HCONTACT
- lParam : HDBCONTACT
- Affect : Called when a new event has been added to the event chain
- for a contact, HCONTACT contains the contact who added the event,
- HDBCONTACT a handle to what was added.
- see notes
- notes : since events are sorted chronologically, you can not guarantee
- that HDBEVEnT is in any particular position in the chain.
-
- }
- ME_DB_EVENT_ADDED = 'DB/Event/Added';
-
- {
- wParam : HANDLE (hContact)
- lParam : @DBEVENTINFO
- Affects: Hook is fired before any DBEVENTS are created within the database for
- a contact (or a user, if hContact is NULL(0)) - It allows a module to
- query/change DBEVENTINFO before it is created, see notes.
- Returns: Hook should return 1 to stop event being added (will stop other hooks seeing the event too)
- Or 0 to continue processing (passing the data on as well)
- Notes : This hook is fired for all event types, and the BLOBS that the eventypes mark
- Maybe changed, therefore be careful about using BLOB formats.
- Because the memory pointing within the DBEVENTINFO CAN NOT BE OWNED or free()'d
- it is recommended that the hook only be used to stop events.
- Version: 0.3.3a+ (2003/12/03)
- }
- ME_DB_EVENT_FILTER_ADD = 'DB/Event/FilterAdd';
-
- {
- wParam : HCONTACT
- lParam : HDBEVENT
- Affect : Called when an event is about to be deleted from the event chain
- for a contact, see notes
- notes : Returning non zero from your hook will NOT stop the deletion,
- but it will as usual stop other hooks being called
- }
- ME_DB_EVENT_DELETED = 'DB/Event/Deleted';
-
-
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Called when a new contact has been added to the database,
- HCONTACT contains a handle to the new contact.
- }
- ME_DB_CONTACT_ADDED = 'DB/Contact/Added';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Called when a contact is about to be deleted
- Returns: Returning nonzero from your hook will not stop the deletion
- but it will stop the other hooks from being called
- }
- ME_DB_CONTACT_DELETED = 'DB/Contact/Deleted';
-
- {
- wParam : HCONTACT
- lParam : Pointer to a TDBCONTACTWRITESETTING
- Affect : Calleed when a contact has one of it's settings changed
- hContact is a valid handle to the contact that has changed,
- see notes.
- notes : this event will be triggered many times rapidly when alot of values
- are set.
- Modules that hook this should be aware of this fact and quickly
- return if they are not interested in the value that has changed.
- Careful not to get into infinite loops with this event,
-
- The TDBCONTACTWRITESETTING pointer is the same one as the
- original service all, so don't change any of it's fields
- }
- ME_DB_CONTACT_SETTINGCHANGED = 'DB/Contact/SettingChanged';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_email.inc b/plugins/ShlExt/inc/m_email.inc deleted file mode 100644 index 93312c7e59..0000000000 --- a/plugins/ShlExt/inc/m_email.inc +++ /dev/null @@ -1,39 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-{$IFNDEF M_EMAIL}
-{$DEFINE M_EMAIL}
-
-const
-
- {
- wParam : HCONTACT
- lParam : 0
- Affects: Send an e-mail to the specified contact, see notes
- Returns: Returns 0 on success or nonzero on failure
- Notes : If an error occurs the service displays a message box
- with the error text -- use this service to alter this
- }
- MS_EMAIL_SENDEMAIL = 'SREMail/SendCommand';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_file.inc b/plugins/ShlExt/inc/m_file.inc deleted file mode 100644 index dd14286455..0000000000 --- a/plugins/ShlExt/inc/m_file.inc +++ /dev/null @@ -1,66 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_FILE}
-{$DEFINE M_FILE}
-
-const
-
- {
- wParam : HCONTACT
- lParam : 0
- Affects: Brings up the send file dialog for a contact, see notes
- Returns: 0 on success [non zero] on failure
- Notes : Returns immediately without waiting for the send
- }
- MS_FILE_SENDFILE = 'SRFile/SendCommand';
-
- {
- wParam : HCONTACT
- lParam : pointer to an array of PChar's the first nil item
- terminates the list -- see notes
- Affects: Brings up the send file dialog with specifieed files already chosen
- the user is not prevented from editing the list --
- Returns: 0 on success [non zero] on failure -- returns immediately without
- waiting for the send to finish
- Notes : both directories and files can be given
- Version: v0.1.2.1+
- }
- MS_FILE_SENDSPECIFICFILES = 'SRFile/SendSpecificFiles';
-
- {
- wParam : HCONTACT
- lParam : Pointer to a buffer
- Affects: returns the received files folder for a contact, the buffer
- should be at least MAX_PATH long (defined with WinAPI),
- the returned path may not exist -- see notes
- Returns: Returns 0 on success [non zero] on failure
- notes : If HCONTACT is NULL(0) the path returned is the path
- without the postfix contact name.
- Version: v0.1.2.2+
- }
- MS_FILE_GETRECEIVEDFILESFOLDER = 'SRFile/GetReceivedFilesFolder';
-
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_findadd.inc b/plugins/ShlExt/inc/m_findadd.inc deleted file mode 100644 index 61b0d066b1..0000000000 --- a/plugins/ShlExt/inc/m_findadd.inc +++ /dev/null @@ -1,38 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-{$IFNDEF M_FINDADD}
-{$DEFINE M_FINDADD}
-
-const
-
- {
- wParam : 0
- lParam : 0
- Affects: Openss the find/add users dialog box, or gives it focus if it's
- already open.
- Returns: Always returns 0
- }
- MS_FINDADDFINDADD = 'FindAdd/FindAddCommand';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_globaldefs.pas b/plugins/ShlExt/inc/m_globaldefs.pas deleted file mode 100644 index 614719a68c..0000000000 --- a/plugins/ShlExt/inc/m_globaldefs.pas +++ /dev/null @@ -1,99 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFDEF FPC}
- {$PACKRECORDS C}
- {$MODE Delphi}
-{$ENDIF}
-
-unit m_globaldefs;
-
-interface
-
-uses
-
-{$ifdef FPC}
- strings;
-{$else}
- Windows;
-{$endif}
-
-type
-
- PByte = ^Byte;
- int = Integer;
- pint = ^int;
- WPARAM = Integer;
- LPARAM = Integer;
- DWORD = Integer;
- THandle = Integer;
-
- // strcpy()
-
- {$ifdef FPC}
- TStrCpy = function(Dst, Src: PChar): PChar;
- {$else}
- TStrCpy = function(Dst, Src: PChar): PChar; stdcall;
- {$endif}
-
- // strcat()
-
- {$ifdef FPC}
- TStrCat = function(Dst, Src: PChar): PChar;
- {$else}
- TStrCat = function(Dst, Src: PChar): PChar; stdcall;
- {$endif}
-
-const
-
- {$ifdef FPC}
- strcpy: TStrCpy = strings.strcopy;
- {$else}
- strcpy: TStrCpy = lstrcpy;
- {$endif}
-
- {$ifdef FPC}
- strcat: TStrCat = strings.strcat;
- {$else}
- strcat: TStrCat = lstrcat;
- {$endif}
-
- {$include newpluginapi.inc}
- {$include m_v8.inc}
-
-var
- { this is now a pointer to a record of function pointers to match the C API,
- and to break old code and annoy you. }
-
- PLUGINLINK: PPLUGINLINK;
-
- { has to be returned via MirandaPluginInfo and has to be statically allocated,
- this means only one module can return info, you shouldn't be merging them anyway! }
-
- PLUGININFO: TPLUGININFO;
- PLUGININFOEX: TPLUGININFOEX;
-
-implementation
-
-end.
diff --git a/plugins/ShlExt/inc/m_globaldefs.ppu b/plugins/ShlExt/inc/m_globaldefs.ppu Binary files differdeleted file mode 100644 index dff0527ff7..0000000000 --- a/plugins/ShlExt/inc/m_globaldefs.ppu +++ /dev/null diff --git a/plugins/ShlExt/inc/m_helpers.inc b/plugins/ShlExt/inc/m_helpers.inc deleted file mode 100644 index ef8edeb088..0000000000 --- a/plugins/ShlExt/inc/m_helpers.inc +++ /dev/null @@ -1,613 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$ifdef M_API_UNIT}
-
- function PLUGIN_MAKE_VERSION(a,b,c,d: Cardinal): int;
- function PLUGIN_CMP_VERSION(verA: LongInt; verB: LongInt): int;
-
-{$else}
-
- function PLUGIN_MAKE_VERSION(a,b,c,d: Cardinal): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := (a shl 24) or (b shl 16) or (c shl 8) or d;
- end;
-
- function PLUGIN_CMP_VERSION(verA: LongInt; verB: LongInt): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := 0;
- { could be used to compare for severity of age for positive values, if a<b
- results are minus values, 0 for equal, positive if a is newer }
- Inc(Result, (verA and $FF) - (verB and $FF));
- Inc(Result, (verA and $FF00) - (verB and $FF00));
- Inc(Result, (verA and $FF0000) - (verB and $FF0000));
- Inc(Result, (verA and $FF000000) - (verB and $FF000000));
- end;
-
-{$endif}
-
-{$ifdef M_SYSTEM}
- {$ifdef M_API_UNIT}
-
- function CallService(const szService: PChar; wParam: WPARAM; lParam: LPARAM): int;
-
- function HookEvent(const szHook: PChar; hook_proc: TMIRANDAHOOK): int;
-
- function CreateServiceFunction(const szName: PChar; const MirandaService: TMIRANDASERVICE): int;
-
- {$else}
-
- function CallService(const szService: PChar; wParam: WPARAM; lParam: lParam): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := PluginLink^.CallService(szService, wParam, lParam);
- end;
-
- function HookEvent(const szHook: PChar; hook_proc: TMIRANDAHOOK): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := PluginLink^.HookEvent(szHook, @hook_proc);
- end;
-
- function CreateServiceFunction(const szName: PChar; const MirandaService: TMIRANDASERVICE): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := PluginLink^.CreateServiceFunction(szName, @MirandaService);
- end;
-
- {$endif}
-
-{$endif}
-
-{$ifdef M_DATABASE}
-
- {$ifdef M_API_UNIT}
-
- function DBGetContactSettingByte(hContact: THandle;
- const szModule: PChar; const szSetting: PChar; errorValue: Integer): Integer;
-
- function DBGetContactSettingWord(hContact: THandle;
- const szModule: PChar; const szSetting: PChar; errorValue: Integer): Integer;
-
- function DBGetContactSettingDword(hContact: THandle;
- const szModule: PChar; const szSetting: PChar; errorValue: Integer): Integer;
-
- function DBGetContactSetting(hContact: THandle;
- const szModule: PChar; const szSetting: PChar; dbv: PDBVARIANT): Integer;
-
- function DBFreeVariant(dbv: PDBVARIANT): Integer;
-
- function DBDeleteContactSetting(hContact: THandle; const szModule: PChar; const szSetting: PChar): Integer;
-
- function DBWriteContactSettingByte(hContact: THandle; const szModule: PChar; const szSetting: PChar; val: Byte): Integer;
-
- function DBWriteContactSettingWord(hContact: THandle; const szModule: PChar; const szSetting: PChar; val: Word): Integer;
-
- function DBWriteContactSettingDWord(hContact: THandle; const szModule: PChar; const szSetting: PChar; val: LongInt): Integer;
-
- function DBWriteContactSettingString(hContact: THandle; const szModule: PChar; const szSetting: PChar; const val: PChar): Integer;
-
- {$else}
-
- function DBGetContactSettingByte(hContact: THandle;
- const szModule: PChar; const szSetting: PChar; errorValue: Integer): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- dbv: TDBVARIANT;
- cgs: TDBCONTACTGETSETTING;
- begin
-
- cgs.szModule := szModule;
- cgs.szSetting := szSetting;
- cgs.pValue := @dbv;
-
- If PluginLink^.CallService(MS_DB_CONTACT_GETSETTING, hContact, lParam(@cgs)) <> 0 then
- Result := ErrorValue
- else
- Result := dbv.bVal;
- end;
-
- function DBGetContactSettingWord(hContact: THandle;
- const szModule: PChar; const szSetting: PChar; errorValue: Integer): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- dbv: TDBVARIANT;
- cgs: TDBCONTACTGETSETTING;
- begin
- cgs.szModule := szModule;
- cgs.szSetting := szSetting;
- cgs.pValue := @dbv;
- If PluginLink^.CallService(MS_DB_CONTACT_GETSETTING, hContact, lParam(@cgs)) <> 0 then
- Result := ErrorValue
- else
- Result := dbv.wVal;
- end;
-
- function DBGetContactSettingDword(hContact: THandle;
- const szModule: PChar; const szSetting: PChar; errorValue: Integer): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- dbv: TDBVARIANT;
- cgs: TDBCONTACTGETSETTING;
- begin
- cgs.szModule := szModule;
- cgs.szSetting := szSetting;
- cgs.pValue := @dbv;
- If PluginLink^.CallService(MS_DB_CONTACT_GETSETTING, hContact, lParam(@cgs)) <> 0 then
- Result := ErrorValue
- else
- Result := dbv.dVal;
- end;
-
- function DBGetContactSetting(hContact: THandle;
- const szModule: PChar; const szSetting: PChar; dbv: PDBVARIANT): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- cgs: TDBCONTACTGETSETTING;
- begin
- cgs.szModule := szModule;
- cgs.szSetting := szSetting;
- cgs.pValue := dbv;
- Result := PluginLink^.CallService(MS_DB_CONTACT_GETSETTING, hContact, lParam(@cgs));
- end;
-
- function DBFreeVariant(dbv: PDBVARIANT): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := PluginLink^.CallService(MS_DB_CONTACT_FREEVARIANT, 0, lParam(dbv));
- end;
-
- function DBDeleteContactSetting(hContact: THandle; const szModule: PChar; const szSetting: PChar): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- cgs: TDBCONTACTGETSETTING;
- begin
- cgs.szModule := szModule;
- cgs.szSetting := szSetting;
- Result := PluginLink^.CallService(MS_DB_CONTACT_DELETESETTING, hContact, lParam(@cgs));
- end;
-
- function DBWriteContactSettingByte(hContact: THandle; const szModule: PChar; const szSetting: PChar; val: Byte): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- cws: TDBCONTACTWRITESETTING;
- begin
- cws.szModule := szModule;
- cws.szSetting := szSetting;
- cws.value.type_ := DBVT_BYTE;
- cws.value.bVal := Val;
- Result := PluginLink^.CallService(MS_DB_CONTACT_WRITESETTING, hContact, lParam(@cws));
- end;
-
- function DBWriteContactSettingWord(hContact: THandle; const szModule: PChar; const szSetting: PChar; val: Word): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- cws: TDBCONTACTWRITESETTING;
- begin
- cws.szModule := szModule;
- cws.szSetting := szSetting;
- cws.value.type_ := DBVT_WORD;
- cws.value.wVal := Val;
- Result := PluginLink^.CallService(MS_DB_CONTACT_WRITESETTING, hContact, lParam(@cws));
- end;
-
- function DBWriteContactSettingDWord(hContact: THandle; const szModule: PChar; const szSetting: PChar; val: LongInt): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- cws: TDBCONTACTWRITESETTING;
- begin
- cws.szModule := szModule;
- cws.szSetting := szSetting;
- cws.value.type_ := DBVT_DWORD;
- cws.value.dVal := Val;
- Result := PluginLink^.CallService(MS_DB_CONTACT_WRITESETTING, hContact, lParam(@cws));
- end;
-
- function DBWriteContactSettingString(hContact: THandle; const szModule: PChar; const szSetting: PChar; const val: PChar): Integer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- cws: TDBCONTACTWRITESETTING;
- begin
- cws.szModule := szModule;
- cws.szSetting := szSetting;
- cws.value.type_ := DBVT_ASCIIZ;
- cws.value.pszVal := Val;
- Result := PluginLink^.CallService(MS_DB_CONTACT_WRITESETTING, hContact, lParam(@cws));
- end;
-
- {$endif}
-
-{$endif}
-
-{$ifdef M_NETLIB}
-
- {$ifdef M_API_UNIT}
-
- function Netlib_CloseHandle(Handle: THandle): int;
-
- function Netlib_GetBase64DecodedBufferSize(const cchEncoded: int): int;
-
- function Netlib_GetBase64EncodedBufferSize(const cbDecoded: int): int;
-
- function Netlib_Send(hConn: THandle; const buf: PChar; len: int; flags: int): int;
-
- function Netlib_Recv(hConn: THandle; const buf: PChar; len: int; flags: int): int;
-
- procedure Netlib_Log(hNetLib: THandle; const sz: PChar);
-
- {$else}
-
- function Netlib_CloseHandle(Handle: THandle): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := PluginLink^.CallService(MS_NETLIB_CLOSEHANDLE, Handle, 0);
- end;
-
- function Netlib_GetBase64DecodedBufferSize(const cchEncoded: int): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := (cchEncoded shr 2) * 3;
- end;
-
- function Netlib_GetBase64EncodedBufferSize(const cbDecoded: int): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := (cbDecoded * 4+11) div 12*4+1;
- end;
-
- function Netlib_Send(hConn: THandle; const buf: PChar; len: int; flags: int): int;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- nlb: TNETLIBBUFFER;
- begin
- nlb.buf := buf;
- nlb.len := len;
- nlb.flags := flags;
- Result := PluginLink^.CallService(MS_NETLIB_SEND, wParam(hConn), lParam(@nlb));
- end;
-
- function Netlib_Recv(hConn: THandle; const buf: PChar; len: int; flags: int): int;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- nlb: TNETLIBBUFFER;
- begin
- nlb.buf := buf;
- nlb.len := len;
- nlb.flags := flags;
- Result := PluginLink^.CallService(MS_NETLIB_RECV, wParam(hConn), lParam(@nlb));
- end;
-
- procedure Netlib_Log(hNetLib: THandle; const sz: PChar);
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- PluginLink^.CallService(MS_NETLIB_LOG, hNetLib, lParam(sz));
- end;
-
- {$endif}
-
-{$endif}
-
-{$ifdef M_UTILS}
-
- {$ifdef M_API_UNIT}
-
- function WindowList_Add(hList: THandle; hWnd: HWND; hContact: THandle): int;
-
- function WindowList_Remove(hList: THandle; hWnd: THandle): int;
-
- function WindowList_Find(hList: THandle; hContact: THandle): int;
-
- function WindowList_Broadcast(hList: THandle; message: int; wParam: WPARAM; lParam: LPARAM): int;
-
- function Utils_SaveWindowPosition(hWnd: THandle; hContact: THandle; const szModule, szNamePrefix: PChar): int;
-
- function Utils_RestoreWindowPosition(hWnd: THandle; hContact: THandle; Flags: int; const szModule, szNamePrefix: PChar): int;
-
- {$else}
-
- function WindowList_Add(hList: THandle; hWnd: hWnd; hContact: THandle): int;
- var
- wle: TWINDOWLISTENTRY;
- begin
- wle.hList := hList;
- wle.hWnd := hWnd;
- wle.hContact := hContact;
- Result := PluginLink^.CallService(MS_UTILS_ADDTOWINDOWLIST, 0, lParam(@wle));
- end;
-
- function WindowList_Remove(hList: THandle; hWnd: THandle): int;
- begin
- Result := PluginLink^.CallService(MS_UTILS_REMOVEFROMWINDOWLIST, hList, hWnd);
- end;
-
- function WindowList_Find(hList: THandle; hContact: THandle): int;
- begin
- Result := PluginLink^.CallService(MS_UTILS_FINDWINDOWINLIST, hList, hContact);
- end;
-
- function WindowList_Broadcast(hList: THandle; message: int; wParam: WPARAM; lParam: LPARAM): int;
- var
- msg: TMSG;
- begin
- msg.message := message;
- msg.wParam := wParam;
- msg.lParam := lParam;
- Result := PluginLink^.CallService(MS_UTILS_BROADCASTTOWINDOWLIST, hList, Integer(@Msg));
- end;
-
- function Utils_SaveWindowPosition(hWnd: THandle; hContact: THandle; const szModule, szNamePrefix: PChar): int;
- var
- swp: TSAVEWINDOWPOS;
- begin
- swp.hWnd := hWnd;
- swp.hContact := hContact;
- swp.szModule := szModule;
- swp.szNamePrefix := szNamePrefix;
- Result := PluginLink^.CallService(MS_UTILS_SAVEWINDOWPOSITION, 0, lParam(@swp));
- end;
-
- function Utils_RestoreWindowPosition(hWnd: THandle; hContact: THandle; Flags: int; const szModule, szNamePrefix: PChar): int;
- var
- swp: TSAVEWINDOWPOS;
- begin
- swp.hWnd := hWnd;
- swp.hContact := hContact;
- swp.szModule := szModule;
- swp.szNamePrefix := szNamePrefix;
- Result := PluginLink^.CallService(MS_UTILS_RESTOREWINDOWPOSITION, Flags, lParam(@swp));
- end;
-
- {$endif}
-
-{$endif}
-
-{$ifdef M_LANGPACK}
-
- {$ifdef M_API_UNIT}
-
- function Translate(sz: PChar): PChar;
-
- function TranslateString(sz: string): string;
-
- function TranslateDialogDefault(hwndDlg: THandle): int;
-
- {$else}
-
- function Translate(sz: PChar): PChar;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- { the return value maybe NULL(0) -- it's upto the caller to know if the allocated
- string has to be removed from the DLL heap, this has little to do with Miranda,
- but if a dynamic string is passed and a return string is used -- the dynamic
- string is lost -- be careful, lazy? use TranslateString (note it's slower) }
- Result := PChar(PluginLink^.CallService(MS_LANGPACK_TRANSLATESTRING, 0, lParam(sz)));
- end;
-
- function TranslateString(sz: string): string;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := string(PChar( PluginLink^.CallService(MS_LANGPACK_TRANSLATESTRING, 0, lParam(sz))));
- end;
-
- function TranslateDialogDefault(hwndDlg: THandle): int;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- lptd: TLANGPACKTRANSLATEDIALOG;
- begin
- lptd.cbSize := sizeof(lptd);
- lptd.flags := 0;
- lptd.hwndDlg := hwndDlg;
- lptd.ignoreControls := nil;
- Result := PluginLink^.CallService(MS_LANGPACK_TRANSLATEDIALOG, 0, lParam(@lptd));
- end;
-
- {$endif}
-
-{$endif}
-
-{$ifdef M_PROTOCOLS}
- {$ifdef M_API_UNIT}
-
- function CallContactService(hContact: THandle; const szProtoService: PChar; wParam: WPARAM; lParam: LPARAM): int;
-
- function CallProtoService(const szModule, szService: PChar; wParam: WPARAM; lParam: LPARAM): int;
-
- {$else}
-
- function CallContactService(hContact: THandle; const szProtoService: PChar; wParam: WPARAM; lParam: LPARAM): int;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- css: TCCSDATA;
- begin
- css.hContact := hContact;
- css.szProtoService := szProtoService;
- css.wParam := wParam;
- css.lParam := lParam;
- Result := PluginLink^.CallService(MS_PROTO_CALLCONTACTSERVICE, 0, Integer(@css));
- end;
-
- function CallProtoService(const szModule, szService: PChar; wParam: WPARAM; lParam: LPARAM): int;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- szStr: array[0..MAXMODULELABELLENGTH] of Char;
- begin
- strcpy(szStr, szModule);
- strcat(szStr, szService);
- Result := PluginLink^.CallService(szStr, wParam, lParam);
- end;
-
- {$endif}
-{$endif}
-
-{$ifdef M_PROTOMOD}
- {$ifdef M_API_UNIT}
-
- function ProtoBroadcastAck(const szModule: PChar; hContact: THandle; type_: int; result_: int; hProcess: THandle; lParam: LPARAM): int;
-
- function CreateProtoServiceFunction(const szModule, szService: PChar; serviceProc: TMIRANDASERVICE): int;
-
- {$else}
-
- function ProtoBroadcastAck(const szModule: PChar; hContact: THandle; type_: int; result_: int; hProcess: THandle; lParam: LPARAM): int;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- ack: TACKDATA;
- begin
- ack.cbSize := sizeof(TACKDATA);
- ack.szModule := szModule;
- ack.hContact := hContact;
- ack.type_ := type_;
- ack.result_ := result_;
- ack.hProcess := hProcess;
- ack.lParam := lParam;
- Result := PluginLink^.CallService(MS_PROTO_BROADCASTACK, 0, Integer(@ack));
- end;
-
- function CreateProtoServiceFunction(const szModule, szService: PChar; serviceProc: TMIRANDASERVICE): int;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- szStr: array[0..MAXMODULELABELLENGTH] of Char;
- begin
- strcpy(szStr, szModule);
- strcat(szStr, szService);
- Result := PluginLink^.CreateServiceFunction(szStr, @serviceProc);
- end;
-
- {$endif}
-
-{$endif}
-
-{$ifdef M_SKIN}
-
- {$ifdef M_API_UNIT}
-
- function LoadSkinnedIcon(id: int): THandle;
-
- function LoadSkinnedProtoIcon(const szProto: PChar; status: int): THandle;
-
- function SkinAddNewSound(const name, description, defaultFile: PChar): int;
-
- function SkinPlaySound (const name: PChar): int;
-
- {$else}
-
- function LoadSkinnedIcon(id: int): THandle;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := PluginLink^.CallService(MS_SKIN_LOADICON, id, 0);
- end;
-
- function LoadSkinnedProtoIcon(const szProto: PChar; status: int): THandle;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := PluginLink^.CallService(MS_SKIN_LOADPROTOICON, wParam(szProto), status);
- end;
-
- function SkinAddNewSound(const name, description, defaultFile: PChar): int;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- ssd: TSKINSOUNDDESC;
- begin
- ssd.cbSize := sizeof(ssd);
- ssd.pszName := name;
- ssd.pszDescription := description;
- ssd.pszDefaultFile := defaultFile;
- Result := PluginLink^.CallService(MS_SKIN_ADDNEWSOUND, 0, lParam(@ssd));
- end;
-
- function SkinPlaySound (const name: PChar): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := PluginLink^.CallService(MS_SKIN_PLAYSOUND, 0, lParam(name));
- end;
-
- {$endif}
-
-{$endif}
diff --git a/plugins/ShlExt/inc/m_history.inc b/plugins/ShlExt/inc/m_history.inc deleted file mode 100644 index 325afad909..0000000000 --- a/plugins/ShlExt/inc/m_history.inc +++ /dev/null @@ -1,37 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-{$IFNDEF M_HISTORY}
-{$DEFINE M_HISTORY}
-
-const
-
- {
- wParam : HCONTACT
- lParam : 0
- Affects: Show's the history dialog box for a contact, see notes
- Notes : HCONTACT can be NULL(0) to show system messages
- }
- MS_HISTORY_SHOWCONTACTHISTORY = 'History/ShowContactHistory';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_icq.inc b/plugins/ShlExt/inc/m_icq.inc deleted file mode 100644 index d359eae928..0000000000 --- a/plugins/ShlExt/inc/m_icq.inc +++ /dev/null @@ -1,191 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_ICQ}
-{$DEFINE M_ICQ}
-
-const
-
- // extra database event type
- ICQEVENTTYPE_WEBPAGER = 2003;
-
- // extra flags for PSS_MESSAGE
- PIMF_ROUTE_DEFAULT = 0;
- PIMF_ROUTE_DIRECT = $10000;
- PIMF_ROUTE_THRUSERVER = $20000;
- PIMF_ROUTE_BESTWAY = $30000;
- PIMF_ROUTE_MASK = $30000;
-
- // for SMS
-
- ICQACKTYPE_SMS = 1001;
- ICQEVENTTYPE_SMS = 2001; // database event type
-
- // for e-mail express
-
- {
- BLOB:
- text: ASCIIZ usually in the form "Subject: %s\r\n%s"
- from-name: ASCIIZ
- from-e-mail: ASCIIZ
- }
-
- ICQEVENTTYPE_EMAILEXPRESS = 2002;
-
- // for server side lists, used internally only
-
- // hProcess=dwSequence, lParam=server's error code, 0 for success
- ICQACKTYPE_SERVERCLIST = 1003;
-
-{$ifndef m_protosvc}
- {$include m_protosvc.inc}
-{$endif}
-
-type
-
- PICQSEARCHRESULT = ^TICQSEARCHRESULT;
- TICQSEARCHRESULT = record
- hdr: TPROTOSEARCHRESULT;
- uin: DWORD;
- auth: Byte;
- end;
-
- PICQDETAILSSEARCH = ^TICQDETAILSSEARCH;
- TICQDETAILSSEARCH = record
- nick: PChar;
- firstName: PChar;
- lastNamee: PChar;
- end;
-
-const
-
- {
- wParam : 0
- lParam : null terminated string containing e-mail to search
- affects: Start a search for all ICQ users by e-mail -- see notes
- returns: Returnss a handle to the search on success, NULL(0) on failure
- notes : uses the same scheme as PSS_BASICSEARCH,
- *DEPRECATED* in favour of PS_SEARCHBYEMAIL
- }
- MS_ICQ_SEARCHBYEMAIL = 'ICQ/SearchByEmail';
-
- {
- wParam : 0
- lParam : POinter to a TICQDETAILSSEARCH structure
- Affect : Start a search of all ICQ users by details, see notes
- Returns: A handle to the search on success, NULL(0) on failure
- Notes : Results are returned in the same scheme as in PSS_BASICSEARCH,
- Not recommended, use PS_SEARCHBYNAME
- }
- MS_ICQ_SEARCHBYDETAILS = 'ICQ/SearchByDetails';
-
- {
- wParam : Pointer to a null terminated string containing phone number
- lParam : Pointer to a null terminated string containing the message
- Affect : Send an SMS via the ICQ network, See notes
- Returns: Handle to the send on success, NULL(0) on failure
- Notes : the phone number should be the full number with internation code
- and prefixed by + e.g. +44<numba>
- }
- MS_ICQ_SENDSMS = 'ICQ/SendSMS';
-
- {
- wParam : level
- lParam : null terminated string containing logging message
- Affect : a logging message was sent from ICQLib
- }
- ME_ICQ_LOG = 'ICQ/Log';
-
-{$ENDIF}
-
- {$ifdef __}
-//Changing user info:
-//See documentation of PS_CHANGEINFO
-//The changing user info stuff built into the protocol is purposely extremely
-//thin, to the extent that your data is passed as-is to the server without
-//verification. Don't mess up.
-//Everything is byte-aligned
-//WORD: 2 bytes, little-endian (that's x86 order)
-//DWORD: 4 bytes, little-endian
-//LNTS: a WORD containing the length of the string, followed by the string
-// itself. No zero terminator.
-#define ICQCHANGEINFO_MAIN 0xEA03
-/* pInfoData points to:
- WORD datalen
- LNTS nick
- LNTS first
- LNTS last
- LNTS email
- LNTS city
- LNTS state
- LNTS phone
- LNTS fax
- LNTS street
- LNTS cellular (if SMS-able string contains an ending ' SMS')
- LNTS zip
- WORD country
- BYTE gmt
- BYTE unknown, usually 0
-*/
-#define ICQCHANGEINFO_MORE 0xFD03
-/* pInfoData points to:
- WORD datalen
- BYTE age
- BYTE 0
- BYTE sex
- LNTS homepage
- WORD birth-year
- BYTE birth-month
- BYTE birth-day
- BYTE lang1
- BYTE lang2
- BYTE lang3
-*/
-#define ICQCHANGEINFO_ABOUT 0x0604
-/* pInfoData points to:
- WORD datalen
- LNTS about
-*/
-#define ICQCHANGEINFO_WORK 0xF303
-/* pInfoData points to:
- WORD datalen
- LNTS city
- LNTS state
- DWORD 0
- LNTS street
- LNTS zip
- WORD country
- LNTS company-name
- LNTS company-dept
- LNTS company-position
- WORD 0
- LNTS company-web
-*/
-#define ICQCHANGEINFO_PASSWORD 0x2E04
-/* pInfoData points to:
- WORD datalen
- LNTS newpassword
-*/
- {$endif}
-
diff --git a/plugins/ShlExt/inc/m_ignore.inc b/plugins/ShlExt/inc/m_ignore.inc deleted file mode 100644 index e4c9e3c062..0000000000 --- a/plugins/ShlExt/inc/m_ignore.inc +++ /dev/null @@ -1,74 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-{$IFNDEF M_IGNORE}
-{$DEFINE M_IGNORE}
-
- { this module only provides UI and storage for blocking only, protocol modules
- are responsible for implementing the block }
-
-const
-
- IGNOREEVENT_ALL = LPARAM(-1);
- IGNOREEVENT_MESSAGE = 1;
- IGNOREEVENT_URL = 2;
- IGNOREEVENT_FILE = 3;
- IGNOREEVENT_USERONLINE = 4;
- IGNOREEVENT_AUTHORIZATION=5;
- IGNOREEVENT_YOUWEREADDED=6; // 0.3.3a+
-
- {
- wParam : HCONTACT
- lParam : IGNOREEVENT_*
- Affects: Determines if a message type to a contact should be ignored, see notes
- Returns: 0 if the message type MUST be shown [non zero] if it MUST be ignored
- Notes : HCONTACT can be NULL(0) to see what to do with a contact
- that isn't on the list (or is unknown in some way)
- don't use the IGNOREEVENT_ALL type!
- Version: v0.1.0.1+
- }
- MS_IGNORE_ISIGNORED = 'Ignore/IsIgnored';
-
- {
- wParam : HCONTACT
- lParam : IGNOREEVENT_* constant
- Affects: Ignore future messages from a contact, see notes
- Returns: 0 on success, [nonzero] on failure
- Notes : wParam: NULL(0) can be used to see if an unknown contact should be ignored
- or not - you can't SET unknown contact's ignore types, this is to stop
- a plugin allowing certain functions (I guess)
- Version: v0.1.0.1+
- }
- MS_IGNORE_IGNORE = 'Ignore/Ignore';
-
- {
- wParam : HCONTACT
- lParam : IGNOREEVENT_*
- Affects: Receive future messages from a contact -- of the given type, see notes
- Returns: 0 on success, non zero on failure
- Notes : Use NULL(0) for HCONTACT to retrieve the setting for an unknown contact
- Version: v0.1.0.1+
- }
- MS_IGNORE_UNIGNORE = 'Ignore/Unignore';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_langpack.inc b/plugins/ShlExt/inc/m_langpack.inc deleted file mode 100644 index 498f844997..0000000000 --- a/plugins/ShlExt/inc/m_langpack.inc +++ /dev/null @@ -1,82 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_LANGPACK}
-{$DEFINE M_LANGPACK}
-
-const
-
- {
- wParam : 0
- lParam : pointer to a null terminated string
- Affects: Returns a pointer to a localised string, if there is no known
- translation it will return lParam, the return value does *not*
- have to be freed in anyway (if successful) -- see notes
- Returns: a pointer to a null terminated string
- Notes : No check is done to see if Miranda has the required version
- Version: v0.1.1.0+
- }
- MS_LANGPACK_TRANSLATESTRING = 'LangPack/TranslateString';
-
- {
- wParam : 0
- lParam : Pointer to a LANGPACKTRANSLATEDIALOG initialised structure, see notes
- Affects: Translates a dialog into the user's local language
- Returns: 0 on successs [non zero] on failure
- Notes : this service only knows about the following window classes/elements:
- Window titles, STATIC, EDIT, Hyperlink, BUTTON.
- Version: v0.1.1.0+
- }
-
-type
-
- PLANGPACKTRANSLATEDIALOG = ^TLANGPACKTRANSLATEDIALOG;
- TLANGPACKTRANSLATEDIALOG = record
- cbSize: int;
- flags: DWORD;
- hwndDlg: THandle;
- ignoreControls: ^Integer; // pointer to an array of integers? mebbe?
- end;
-
-const
-
- { translate all edit controls, by default non-read-only edit controls are not }
- LPTDF_NOIGNOREEDIT = 1;
- { don't translate the title of the dialog }
- LPTDF_NOTITLE = 2;
-
- MS_LANGPACK_TRANSLATEDIALOG = 'LangPack/TranslateDialog';
-
- {
- wParam : HMENU handle (WinAPI handle to a menu)
- lParam : 0
- Affects: Translates a menu into the user's local language -- see notes
- Returns: 0 on success [non zero] on failure
- Notes : This doesn't work with owner draw menus that store their
- captions in a structure known by the owner -- something to be aware of ;)
- version: v0.1.1.0+
- }
- MS_LANGPACK_TRANSLATEMENU = 'LangPack/TranslateMenu';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_message.inc b/plugins/ShlExt/inc/m_message.inc deleted file mode 100644 index 5cee0040b3..0000000000 --- a/plugins/ShlExt/inc/m_message.inc +++ /dev/null @@ -1,57 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_MESSAGE}
-{$DEFINE M_MESSAGE}
-
-const
-
- {
- wParam : HCONTACT
- lParam : Pointer to a null terminated string
- Affects: brings up the send message dialog for a contact, see notes
- Returns: 0 on success, non zero on failure
- Notes : returns immediately, just after the send dialog is shown,
- the lParam is entered into the editbox of the window,
- but it's not sent.
- Version: v0.1.2.0+ only supports a string, prior NULL(0) is expected
- this service was defined as 'SRMsg/LaunchMessageWindow'
- use both if compatibility use both, the correct one will work,
- but don't rely on the message to be displayed
-
- }
- MS_MSG_SENDMESSAGE = 'SRMsg/SendCommand';
- MS_MSG_SENDMESSAGE_OLD = 'SRMsg/LaunchMessageWindow';
-
- {
- wParam : 0
- lParam : Pointer to a null termed string
- Affects: displays the send message dialog with the 'multiple' option open
- and no contacts selected
- Returns: Returns 0 on success, nonzero on failure
- Version: only present after v0.1.2.1+
- }
- MS_MSG_FORWARDMESSAGE = 'SRMsg/ForwardMessage';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_netlib.inc b/plugins/ShlExt/inc/m_netlib.inc deleted file mode 100644 index 11334c9897..0000000000 --- a/plugins/ShlExt/inc/m_netlib.inc +++ /dev/null @@ -1,713 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_NETLIB}
-{$DEFINE M_NETLIB}
-
-{>>/
-
- NetLib :
-
- Instead of you writing all the code for working with sockets and supporting
- app level protocols such as SOCKS5, it's all done for you.
-
- NetLib takes care of all that and you can even register a special abstract
- nexus, e.g. ICQ direct, the user can configure all this from the options dialog
- and you don't have to bother with any of it.
-
- NetLib wraps up any Winsock calls but you can still get the socket handle
- from your netlib handle and do stuff.
-
- It gives all modules an abstract way of dealing with transport -- mainly sockets
- and proxies, Now the but..
-
- It's new (mmmm) thus unsupported by any older version of Miranda, and if you
- want to be lazy and not write any "wrapper" mini netlib then you'll have
- the kudos of "only works with nightly build version of Miranda" :)
-
-/<<}
-
- {$ifndef M_SYSTEM}
- {$include m_system.inc}
- {$endif}
-
-const
-
- // for TNETLIBUSER.flags
-
- { bind incoming ports }
- NUF_INCOMING = $01;
- { makes outgoing plain connections }
- NUF_OUTGOING = $02;
- { can use HTTP gateway for plain sockets. ???HttpGateway* are valid,
- enables the HTTP proxy option, displayed in options }
- NUF_HTTPGATEWAY = $04;
- { don't show this as an entry for custom settings to be defined for,
- TNETLIB.szDescriptiveName is ignored }
- NUF_NOOPTIONS = $08;
- { some connections are made for HTTP communication,
- enables the HTTP proxy option, displayed in options }
- NUF_HTTPCONNS = $10;
- { Disables the HTTPS proxy option in options, Use this if all communication
- is HTTP }
- NUF_NOHTTPSOPTION = $20;
-
- // for TNETLIBUSERSETTINGS.proxyType
-
- { SOCKS4 -- No DNS or multi addressing mode (proxy side) -- optional username can
- be given, no password }
- PROXYTYPE_SOCKS4 = 1;
- { SOCKS5 -- DNS names can be given as addresses to connect to, optional
- plain text username/password scheme (which may cause failure due to denied access)
- IP address maybe returned for DNS addresses -- thus server side DNS }
- PROXYTYPE_SOCKS5 = 2;
- PROXYTYPE_HTTP = 3;
- PROXYTYPE_HTTPS = 4;
-
- // for TNETLIBOPENCONNECTION.flags
-
- { this connection will be useed for HTTP communications,
- if configured for an HTTP(S) proxy the connection is opened as if there
- was no proxy }
-
- NLOCF_HTTP = $0001;
-
- // for TNETLIBHTTPPROXYINFO.flags
-
- { append sequence numbers to GET requests }
- NLHPIF_USEGETSEQUENCE = $0001;
- { append sequence numbers to POST requests }
- NLHPIF_USEPOSTSEQUENCE = $0002;
- { GET and POST use the same sequence }
- NLHPIF_GETPOSTSAMESEQUENCE = $0004;
-
- // for TNETLIBHTTPREQUEST.flags, .requestType
-
- { used by MS_NETLIB_RECVHTTPHEADERS returned structure }
-
- REQUEST_RESPONSE = 0;
- REQUEST_GET = 1;
- REQUEST_POST = 2;
- REQUEST_CONNECT = 3;
-
- { auto generate a 'host' header from .szUrl }
- NLHRF_GENERATEHOST = $00000001;
- { remove any host and/or protocol portion of szUrl before sending it }
- NLHRF_REMOVEHOST = $00000002;
- { removes host and/or protocol from szUrl unless the connection was
- opened through an HTTP or HTTPS proxy. }
- NLHRF_SMARTREMOVEHOST = $00000004;
- { if the connection was opened through an HTTP or HTTPS proxy then
- send a Proxy-Authorization header if required. }
- NLHRF_SMARTAUTHHEADER = $00000008;
- { never dump this to the log }
- NLHRF_NODUMP = $00010000;
- { don't dump http headers (only useful for POSTs and MS_NETLIB_HTTPTRANSACTION }
- NLHRF_NODUMPHEADERS = $00020000;
- { this transaction is a proxy communication. For dump filtering only. }
- NLHRF_DUMPPROXY = $00040000;
- { dump posted and reply data as text. Headers are always dumped as text. }
- NLHRF_DUMPASTEXT = $00080000;
-
- // for TNETLIBBUFFER.flags
-
- { don't wrap outgoing packet using TNETLIBUSER.pfnHttpGatewayWrapSend }
- MSG_NOHTTPGATEWAYWRAP = $010000;
- { don't dump this packet to the log }
- MSG_NODUMP = $020000;
- { this iss proxy communication, for dump filtering only }
- MSG_DUMPPROXY = $040000;
- { don't dump as hex, it's text }
- MSG_DUMPASTEXT = $080000;
- { send as raw, bybpass HTTP proxy stuff }
- MSG_RAW = $100000;
-
-
- // all record types structures are declared in their own block because the C header
- // file used forward declaration (to get typed parameters for certain function pointers)
- // This sort of define-type-pointer-before-type can only be done in the same type block
- // in D2 (don't know about later versions)
-
-type
-
- { forward typed pointers to records }
-
- PNETLIBOPENCONNECTION = ^TNETLIBOPENCONNECTION;
- PNETLIBHTTPREQUEST = ^TNETLIBHTTPREQUEST;
-
- { This function pointer is to the CRT realloc() used by Miranda -- it allows reallocation of memory passed
- to us (not that we could EVER share the same CRT) but to allow DLLs in general to reallocate memory }
- TNetlibRealloc = function(Mem: Pointer; size_t: int): Pointer; cdecl;
- TNetlibHTTPGatewayInitProc = function(hConn: THandle; nloc: PNETLIBOPENCONNECTION; nlhr: PNETLIBHTTPREQUEST): int; cdecl;
- TNetlibHTTPGatewayBeginProc = function(hConn: THandle; nloc: PNETLIBOPENCONNECTION): int; cdecl;
- TNetlibHTTPGatewayWrapSendProc = function(hConn: THandle; buf: PByte; len: int; flags: int; pfnNetLibSend: TMIRANDASERVICE): int; cdecl;
- TNetlibHTTPGatewayUnwrapRecvProc = function(nlhr: PNETLIBHTTPREQUEST; buf: PByte; len: int; outBufLen: pInt; NetlibRealloc: TNetlibRealloc): PByte; cdecl;
-
- PNETLIBUSER = ^TNETLIBUSER;
- TNETLIBUSER = record
- cbSize: int;
- { used for DB settings and log, 'NL' stuff }
- szSettingsModule: PChar;
- { shows a descriptive name for which different proxy settings can be defined }
- szDescriptiveName: PChar;
- { see NUF_* constants above }
- flags: DWORD;
- szHttpGatewayHello: PChar;
- { can be NULL(0) to send no User-Agent: also used by HTTPS proxies }
- szHttpGatewayUserAgent: PChar;
- pfnHttpGatewayInit: TNetlibHTTPGatewayInitProc;
- { can be NULL(0) if no begin is required }
- pfnHttpGatewayBegin: TNetlibHTTPGatewayBeginProc;
- { can be NULL(0) if no wrapping is required }
- pfnHttpGatewayWrapSend: TNetlibHTTPGatewayWrapSendProc;
- { can be NULL(0) " " }
- pfnHttpGatewayUnwrapRecv: TNetlibHTTPGatewayUnwrapRecvProc;
- { only if NUF_INCOMING, will be used for validation of user input }
- minIncomingPorts: int;
- end;
-
- PNETLIBUSERSETTINGS = ^TNETLIBUSERSETTINGS;
- TNETLIBUSERSETTINGS = record
- { filled before calling }
- cbSize: int;
- { 1 or 0 }
- useProxy: int;
- { PROXYTYPE_* constant, see above }
- proxyType: int;
- { can be NULL(0) }
- szProxyServer: PChar;
- { in host byte order }
- wProxyPort: int;
- { 1 or 0, always 0 for SOCKS4 (doesn't have auth) }
- useProxyAuth: int;
- { can be NULL(0), always used by SOCKS4 }
- szProxyAuthUser: PChar;
- { can be NULL(0) }
- szProxyAuthPassword: PChar;
- { 1 or 0, only used by HTTP, HTTPS }
- useProxyAuthNtlm: int;
- { 1 or 0 }
- dnsThroughProxy: int;
- { 1 or 0 }
- specifyIncomingPorts: int;
- { can be NULL(0), form '1024-1050,1060-1070,2000' }
- szIncomingPorts: PChar;
- end;
-
- TNetlibNewConnectionProc = procedure(hNewConnection: THandle; dwRemoveIP: DWORD); cdecl;
-
- PNETLIBBIND = ^TNETLIBBIND;
- TNETLIBBIND = record
- cbSize: int;
- { function to call when there's a new connection, dwRemoteIP is in host byte
- order -- the handle is to the new connection }
- pfnNewConnection: TNetlibNewConnectionProc;
- { set on return, host byte order }
- dwInternalIP: DWORD;
- { set on return, host byte order }
- wPort: WORD;
- end;
-
- { Pointered type is above }
- TNETLIBOPENCONNECTION = record
- cbSize: int;
- szHost: PChar; // can be an IP in string form
- wPort: Word;
- flags: DWORD; // see NLOCF_* flags
- end;
-
- PNETLIBHTTPPROXYINFO = ^TNETLIBHTTPPROXYINFO;
- TNETLIBHTTPPROXYINFO = record
- cbSize: int;
- { see NLHPIF_* above }
- flags: DWORD;
- szHttpPostUrl: PChar;
- szHttpGetUrl: PChar;
- firstGetSequence: int;
- firstPostSequence: int;
- end;
-
- PNETLIBBASE64 = ^TNETLIBBASE64;
- TNETLIBBASE64 = record
- pszEncoded: PChar;
- cchEncoded: int;
- pbDecoded: PByte;
- cbDecoded: int;
- end;
-
- PNETLIBHTTPHEADER = ^TNETLIBHTTPHEADER;
- TNETLIBHTTPHEADER = record
- szName: PChar;
- szValue: PChar;
- end;
-
- { PNETLIBHTTPREQUEST = ^TNETLIBHTTPREQUEST, defined above because this is
- forward referenced from there }
- TNETLIBHTTPREQUEST = record
- cbSize: int;
- requestType: int; // REQUEST_* constant
- flags: DWORD;
- szUrl: PChar;
- { doesn't contain Content-Length, it'll be added automatically }
- headers: PNETLIBHTTPHEADER; // pointer to an array of em?
- headersCount: int; // yes they do
- pData: PChar; // data to be sent on POST request
- dataLength: int; // must be 0 for REQUEST_GET/REQUEST_CONNECT
- resultCode: int;
- szResultDescr: PChar;
- end;
-
- PNETLIBBUFFER = ^TNETLIBBUFFER;
- TNETLIBBUFFER = record
- buf: PChar;
- len: int;
- { see MSG_* constants above }
- flags: int;
- end;
-
- PNETLIBSELECT = ^TNETLIBSELECT;
- TNETLIBSELECT = record
- cbSize: int;
- dwTimeout: DWORD; // in milliseconds, INFINITE is acceptable
- hReadConns: array[0..64+1] of THandle;
- hWriteConns: array[0..64+1] of THandle;
- hExceptConns: array[0..64+1] of THandle;
- end;
-
- PNETLIBPACKETRECVER = ^TNETLIBPACKETRECVER;
- TNETLIBPACKETRECVER = record
- cbSize: int;
- { infinite is allowed -- initialise before use }
- dwTimeout: DWORD;
- { this many bytes are removed from the start of the buffer,
- set to 0 on return -- initialise before use }
- bytesUsed: int;
- { equal the returnd value by service, unless the return value is 0 (connection closed) }
- bytesAvailable: int;
- { same as the parameter given to MS_NETLIB_CREATEPACKETRECVER: wParam }
- bufferSize: int;
- { contains the read data }
- buffer: PByte;
- end;
-
-const
-
- {
- wParam : 0
- lParam : Pointer to an initalised TNETLIBUSER structure
- Affects: Initialises the netlib for a set of connections, see notes
- Returns: Returns a handle for future netlib calls, NULL on failure.
- Notes : Netlib is loaded AFTER all plugins, thus a call to this service
- in Load() will fail, hook ME_SYSTEM_MODULESLOADED and call it
- from there.
- -
- Netlib will save settings under .szSettings module, all settings
- (being?) begin with 'NL'.
- -
- Defacto settings are the same as <All connections> combobox entry option
- as seen in Miranda->Options->Network
- Version: v0.1.2.2+
- Errors : ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, ERROR_DUP_NAME
- }
- MS_NETLIB_REGISTERUSER = 'Netlib/RegisterUser';
-
- {
- wParam : HANDLE
- lParam : Pointer to a initalised TNETLIBUSERSETTINGS structure
- Affects: Gets the user configured settings for a Netlib user, see notes
- Returns: [non zero] on SUCCESS, NULL(0) on failure
- Notes : .cbSize must be filled with sizeof() before calling --
- the returned null terminated strings (in the structure) are valid
- as long as HANDLE remains open or proxy options are changed
- again, do not rely on them being around forever.
- Version: v0.1.2.2+
- Errors : ERROR_INVALID_PARAMETER
- }
- MS_NETLIB_GETUSERSETTINGS = 'Netlib/GetUserSettings';
-
- {
- wParam : HANDLE
- lParam : Pointer to a initalised NETLIBUSERSETTINGS structure
- Affect : Changes the configurable settings for a Netlib user -- see notes
- Returns: [non zero] on success, NULL(0) on failure
- Notes : This service is only really useful for people that specify NUF_NOOPTIONS
- when registering and want to create their own options.
- Settings will be stored even if the option to enable it, is it not enabled,
- e.g. useProxyAuth is 0, szProxyAuthPassword will still be saved
- Errors : ERROR_INVALID_PARAMETER
- }
- MS_NETLIB_SETUSERSETTINGS = 'Netlib/SetUserSettings';
-
- {
- wParam : HANDLE / SOCKET
- lParam : 0
- Affects: Closes a handle, see notes
- Returns: Returns [non zero] on success, NULL(0) on failure
- Notes : All netlib handles should be closed once they're finished with,
- If a SOCKET type is passed instead of netlib handle type, it is closed
- Errors : ERROR_INVALID_PARAMETER
- }
- MS_NETLIB_CLOSEHANDLE = 'Netlib/CloseHandle';
-
- {
- wParam : HANDLE
- lParam : Pointer to a initialised TNETLIBBIND
- Affects: Open a port and wait for connections on it -- see notes
- Returns: Returns a handle on success, NULL(0) on failure
- Notes : this function does the equivalent of socket(), bind(), getsockname(),
- listen(), accept() -- internally this function creates a new thread
- which waits around in accept() for new connections.
- When one is received, TNETLIBBIND.pfnNewConnection is called,
- from the context of the NEW thread and then it
- returns to waiting for connections.
- -
- Close the returned handle to end the thread and close the port.
- -
- Errors : ERROR_INVALID_PARAMETER, any returned by socket(), bind(), listen()
- getsockname()
- }
- MS_NETLIB_BINDPORT = 'Netlib/BindPort';
-
- {
- wParam : HANDLE
- lParam : Pointer to an initalised TNETLIBOPENCONNECTION structure
- Affects: Opens a connection -- see notes
- Returns: Returns a Handle to a new connection on success, NULL(0) on failure
- Notes : internally this service is the equivalent of socket(), gethostbyname(),
- connect()
- -
- If NLOCF_HTTP is set and HANDLE is configured for HTTP(S) proxy
- then this function will connect() to that proxy server ONLY,
- without performing any initialisation conversation.
- -
- If HANDLE is configured for an HTTP proxy and does not support
- HTTP gateways and you try to open a connection without NLOCF_HTTP
- then this service will first attempt to open an HTTPS connection,
- if that fails, it will try a direct connection, if *that* fails
- then it will return failure with the error
- from connect() during the connection attempt
- Errors : ERROR_INVALID_PARAMETER, any returned by socket(), gethostbyname(),
- connect(), MS_NETLIB_SEND, MS_NETLIB_RECV, select()
- -
- ERROR_TIMEOUT (during proxy communication)
- ERROR_BAD_FORMAT (very invalid proxy reply)
- ERROR_ACCESS_DENIED (by proxy)
- ERROR_CONNECTION_UNAVAIL (socks proxy can't connect to identd)
- ERROR_INVALID_ACCESS (proxy refused identd auth)
- ERROR_INVALID_DATA (proxy returned invalid code)
- ERROR_INVALID_ID_AUTHORITY (proxy requires use of auth method that's not supported)
- ERROR_GEN_FAILURE (socks5/https general failure)
- ERROR_CALL_NOT_IMPLEMENTED (socks5 command not supported)
- ERROR_INVALID_ADDRESS (socks5 address type not supported)
- -
- HTTP: anything from TNETLIBUSER.pfnHttpGatewayInit, TNETLIBUSER.pfnHttpGatewayBegin,
- MS_NETLIB_SENDHTTPREQUEST or MS_NETLIB_RECVHTTPHEADERS
- }
- MS_NETLIB_OPENCONNECTION = 'Netlib/OpenConnection';
-
- {
- wParam : HANDLE
- lParam : Pointer to an initialised NETLIBHTTPPROXYINFO structure
- Affects: Sets the required information for an HTTP proxy connection -- see notes
- Returns: [non zero] on success, NULL(0) on failure
- Notes : This service is designed to be called from
- within TNETLIBUSER.pfnHttpGatewayInit (see notes in C header under
- MS_NETLIB_REGISTERUSER)
- Errors : ERROR_INVALID_PARAMETER
- }
- MS_NETLIB_SETHTTPPROXYINFO = 'Netlib/SetHttpProxyInfo';
-
- {
- wParam : HANDLE
- lParam : 0
- Affects: Get's the SOCKET associated with a handle -- see notes
- Returns: the SOCKET on success, INVALID_SOCKET on failure
- Notes : The Netlib handle passed to this service should only be passed
- if they were returned with MS_NETLIB_OPENCONNECTION or MS_NETLIB_BINDPORT
- -
- Be careful how you use this socket because you might be connected via an
- HTTP proxy, in which case calling send/recv() will break things
- -
- Errors : ERROR_INVALID_PARAMETER
- }
- MS_NETLIB_GETSOCKET = 'Netlib/GetSocket';
-
- {
- wParam : 0
- lParam : Pointer to a null terminated string
- Affects: URL-encodes a string for x-www-form-urlencoded (and other uses) -- see notes
- Returns: A pointer to a null terminated string, NULL(0) on failure
- Notes : The returned string must be freed after it's no longer needed,
- to do this Miranda's process heap must be used (under the WINAPI), e.g.
- HeapFree(GetProcessHeap(), 0, the_returned_string)
- Errors : ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY
- }
- MS_NETLIB_URLENCODE = 'Netlib/UrlEncode';
-
- {
- wParam : 0
- lParam : Pointer to a TNETLIBBASE64 initialised structure
- Affects: Decodes a Base64 null terminated string, see notes
- Returns: [non zero] on success, NULL(0) on failure
- Notes : TNETLIBBASE64.pszEncoded and cchEncoded must contain a pointer to
- a buffer to use as input, and it's length, the length
- should not include space taken for null termination --
- -
- Output is placed in ..pbDecoded and ..cbDecoded for buffer and
- length of buffer -- the maxiumum output for a given input can
- be worked out with Netlib_GetBase64DecodedBufferSize() function
- see below.
- -
- For more information on Base64 see rfc-1421.
- Errors : ERROR_INVALID_PARAMETER, ERROR_INVALID_DATA, ERROR_BUFFER_OVERFLOW
- }
- MS_NETLIB_BASE64DECODE = 'Netlib/Base64Decode';
-
- {
- wParam : 0
- lParam : Pointer to an initialised TNETLIBBASE64 structure
- Affect : Base64 encode a string, see notes
- Returns: [non zero] on success, NULL(0) on failure
- Notes : TNETLIBBASE64.pbDecode and TNETLIBBASE64.cbDecoded contain
- the input buffer and it's length --
- TNETLIBBASE64.pszEncoded and TNETLIBBASE64.cchEncoded contain the
- buffer in which to put the output and it's length.
- -
- The maximum output size for a given input can be worked
- out with the function Netlib_GetBase64EncodedBufferSize() below
- .pszEncoded is null terminated, on return TNETLIBBASE64.cchEncoded
- is set to the actual length excluding 0.
- Errors : ERROR_INVALID_PARAMETER, ERROR_BUFFER_OVERFLOW
- }
- MS_NETLIB_BASE64ENCODE = 'Netlib/Base64Encode';
-
- {
- wParam : HANDLE
- lParam : Pointer to a initialised TNETLIBHTTPREQUEST structure
- Affect : Send an HTTP request over a connection, see notes
- Returns: The number of bytes on success, SOCKET_ERROR on failure
- Notes : HANDLE must of been returned by MS_NETLIB_OPENCONNECTION,,
- If you use NLHRF_SMARTAUTHHEADER and NTLM auth is in use then
- full NTLM auth transcation occurs, comprising sending the
- domain, getting the challenge, sending the response.
- NETLIBHTTPREQUEST.resultCode and NETLIBHTTPREQUEST.szResultDescr are
- ignored by this service.
- Errors : ERROR_INVALID_PARAMETER, MS_NETLIB_SEND (return codes)
- }
- MS_NETLIB_SENDHTTPREQUEST = 'Netlib/SendHttpRequest';
-
- {
- wParam : HANDLE
- lParam : 0
- Affect : Receive HTTP headers, see notes
- Returns: A pointer to a TNETLIBHTTPREQUEST structure on success, NULL(0) on failure
- Notes : The returned pointer must be freed after it's done with
- use MS_NETLIB_FREEHTTPREQUESTSTRUCT.
- -
- HANDLE must be returned by MS_NETLIB_OPENCONNECTION
- -
- Return^.pData=NIL and Return^.dataLength=0 always
- -
- The returned data should be retrieved using MS_NETLIB_RECV once
- the headers have been parsed.
- If headers haven't finished within 60 seconds the function returns
- NULL(0) and ERROR_TIMEOUT
- Errors : ERROR_INVALID_PARAMETER, any MS_NETLIB_RECV or select()
- ERROR_HANDLE_EOF (connection closed bfore headers complete)
- ERROR_TIMEOUT (headers still not complete after 60 seconds)
- ERROR_BAD_FORMAT (invalid character or line ending in headers, or first line is blank)
- ERROR_BUFFER_OVERFLOW (each header line must be less than 4096 chars long)
- ERROR_INVALID_DATA (first header line is malformed ("http/[01].[0-9] [0-9]+ .*", or no colon in subsequent line)
-
- }
- MS_NETLIB_RECVHTTPHEADERS = 'Netlib/RecvHttpHeaders';
-
- {
- wParam : 0
- lParam : Pointer returned by MS_NETLIB_RECVHTTPHEADERS to free
- Affect : Free the memory used by a TNETLIBHTTPREQUEST structure, see notes
- Returns: [non zero] on success, NULL(0) on failure
- Notes : This service should only be used with memory pointers returned
- by either MS_NETLIB_RECVHTTPHEADERS or MS_NETLIB_HTTPTRANSACTION!.
- Errors : ERROR_INVALID_PARAMETER
-
- }
- MS_NETLIB_FREEHTTPREQUESTSTRUCT = 'Netlib/FreeHttpRequestStruct';
-
- {
- wParam : HANDLE
- lParam : Pointer to a TNETLIBHTTPREQUEST structure
- Affect : Carry out an entire HTTP transaction, see notes
- Returns: another pointer to a TNETLIBHTTPREQUEST structure or NULL(0)
- on failure
- Notes : The returned pointer must be freed at some point
- with MS_NETLIB_FREEHTTPREQUESTSTRUCT,
- -
- TNETLIBHTTPREQUEST.szUrl should have a full HTTP URL, if it
- does not start with http://, that will be assumed, but do not
- take this assumption to stay assumed (heh..) in the future
- -
- this service equivalent of open(), sendhttp(), getheaders()
- netlib_recv(), netlib_closehandle()
- -
- TNETLIBHTTPREQUEST.headers will be added to with the following
- headers if they're not already present :
- "Host" (even if it is requested in .flags)
- "User-Agent" (in form : 'Miranda/d.d.d.d <(status of release)>')
- "Content-Length" (for POSTs only, set to TNETLIBHTTPREQUEST.dataLength)
-
- If you don't want to send any of these headers --
- set TNETLIBHTTPREQUEST.headers to NULL(0)
- -
- In the returned pointer, pData[dataLen] is always 0 for 'safety'
- also : headers, headersCount, pData, dataLength, resultCode and
- szResultDescr are all valid
- -
- Also take care not to assume that a returned pointer means that
- at the HTTP level it all worked out -- refer to the resultCode for
- 2xx before doing anything else
- -
- Errors : ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY
- Errors returned by the aforementioned internally used functions
- }
- MS_NETLIB_HTTPTRANSACTION = 'Netlib/HttpTransaction';
-
- {
- wParam : HANDLE
- lParam : Pointer to an initialised TNETLIBBUFFER structure
- Affect : Send data over an open connection see notes
- Returns: The number of bytes sent on success, SOCKET_ERROR on failure
- Notes : see Netlib_Send() helper function
- Errors : ERROR_INVALID_PARAMETER,
- anything from socket(), connect()
- send(), TNETLIBUSER.pfnHttpGatewayWrapSend(),
- (HTTP proxy): ERROR_GEN_FAILURE (http result code wasn't 2xx)
- MS_NETLIB_SENDHTTPREQUEST, MS_NETLIB_RECVHTTPHEADERS
- }
- MS_NETLIB_SEND = 'Netlib/Send';
-
- {
- wParam : HANDLE
- lParam : Pointer to an initialised TNETLIBBUFFER structure
- Affect : Receive data over a connection, see notes
- Returns: The number of bytes read on success, SOCKET_ERROR on failure
- Notes :
- This service uses some of the same flags as MS_NETLIB_SEND :
- MSG_PEEK,
- MSG_NODUMP,
- MSG_DUMPPROXY,
- MSG_NOHTTPGATEWAYWRAP,
- MSG_DUMPASTEXT,
- MSG_RAW
- -
- On using MSG_NOHTTPGATEWAYWRAP: Because packets through an HTTP proxy are
- batched and cached and stuff, using this flag is not a guarantee that it
- will be obeyed, and if it is it may even be propogated to future calls
- even if you don't specify it then. Because of this, the flag should be
- considered an all-or-nothing thing: either use it for the entire duration
- of a connection, or not at all.
- Errors : ERROR_INVALID_PARAMETER, anything from recv()
- (HTTP proxy):
- ERROR_GEN_FAILURE (http result code wasn't 2xx)
- ERROR_INVALID_DATA (no Content-Length header in reply)
- ERROR_NOT_ENOUGH_MEMORY (Content-Length very large)
- ERROR_HANDLE_EOF (connection closed before Content-Length bytes recved)
- anything from select(),
- MS_NETLIB_RECVHTTPHEADERS, nlu.pfnHttpGatewayUnwrapRecv, socket(),
- connect(), MS_NETLIB_SENDHTTPREQUEST
-
- }
- MS_NETLIB_RECV = 'Netlib/Recv';
-
- {
- wParam : 0
- lParam : Pointer to an initialised TNETLIBSELECT structure
- Affect : Determine the status of one or more connections, see notes
- Returns: The numbe of ready connections, SOCKET_ERROR on failure
- Notes : All handles passed to this service must have been returned
- either by MS_NETLIB_OPENCONNECTION or MS_NETLIB_BINDPORT,
- the last handle in each list must be followed by either NULL
- or INVALID_HANDLE_VALUE.
- Errors : ERROR_INVALID_HANDLE, ERROR_INVALID_DATA, anything from select()
- }
- MS_NETLIB_SELECT = 'Netlib/Select';
-
- {
- wParam : HANDLE
- lParam : maxPacketSize
- Affect : Create a packet receiver, see notes
- Returns: A handle on success, NULL(0) on failure
- Notes : The packet receiver implements the common situation where
- you have a variable length of packets coming thru over a connection
- and you want them split up in order to handle them.
- -
- The major limiation is, that the buffer is created in memory,
- so you can't have arbitrarily large packets
- Errors : ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY
- }
- MS_NETLIB_CREATEPACKETRECVER = 'Netlib/CreatePacketRecver';
-
- {
- wParam : Handle returned by MS_NETLIB_CREATEPACKETRECVER
- lParam : Pointer to an initialised TNETLIBPACKETRECVER
- Returns: The total number of bytes available in the buffer, NULL(0)
- if the connection was closed or SOCKET_ERROR.
- -
- If TNETLIBPACKETRECVER.bytesUsed is set to zero and the
- buffer is already full up to the maxPacketSize, it is assumed
- that a too large packet has been received, All data in
- the buffer is discarded and receiving has started anew.
- -
- This will probably cause alignment problem so if you think
- that tis iss likely to happen, then you should deal with it
- yourself.
- -
- Closing the packet receiver will not close the associated
- connection but will discard any bytes still in the buffer,
- so if you intend to carry on reading from that connection,
- make sure you have processed the buffer first.
- -
- This service is equivalent of memmove() to remove
- the first bytesUsed from the buffer, select(), if dwTimeOut
- is not INFINITE, then MS_NETLIB_RECV
- Errors : ERROR_INVALID_PARAMETER, ERROR_TIMEOUT, anything from select(),
- MS_NETLIB_RECV
- }
- MS_NETLIB_GETMOREPACKETS = 'Netlib/GetMorePackets';
-
- {
- wParam : HANDLE
- lParam : Pointer to null terminated string to uh, log.
- Affect : Add a message to the log (if it's running) see notes
- Returns: non zeror on success, NULL(0) on failure
- Notes : Don't include \r\n or #13#10 it's not needed,
- -
- Doesn't support formatting like the given C code for
- Netlib_Logf, just use FmtStr() and then call this service
- if you want that.
- Errors : ERROR_INVALID_PARAMETER
- }
- MS_NETLIB_LOG = 'Netlib/Log';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_options.inc b/plugins/ShlExt/inc/m_options.inc deleted file mode 100644 index 6a011fecdc..0000000000 --- a/plugins/ShlExt/inc/m_options.inc +++ /dev/null @@ -1,109 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_OPTIONS}
-{$DEFINE M_OPTIONS}
-
-const
-
- {
- wParam : addinfo
- lParam : 0
- Affects: The user opened the options dialog, see notes
- Notes : Modules should do whatever initalisation they need and call
- MS_OPT_ADDPAGE with the wParam -- MS_OPT_ADDPAGE
- can be called one or more times
- if more than one page wants to be displayed.
- }
- ME_OPT_INITIALISE = 'Opt/Initialise';
-
- {
- wParam : wParam from ME_OPT_INITIALISE
- lParam : Pointer to an initialised TOPTIONSDIALOGPAGE
- Affects: Adds a page to the options dialog, see notes
- Notes : Strings in the structure can be released as soon as the
- service returns -- but icons must be kept around, this iss
- not a problem if you're loading theem from a resource.
- -
- This service should only be called within the ME_OPT_INITIALISE
- event hook.
- -
- Pages in the options dialog operate just like pages in property
- sheets, See the WinAPI documentation for details on how they operate.
- Version: Prior to v0.1.2.1 the options dialog would resize
- to fit the largest page, but since then it's a fixed size
- The largest page that fits neatly is 314x240 DLU's
- -
- Some of OPTIONSDIALOGPAGE's fields are version dependant.
- }
- MS_OPT_ADDPAGE = 'Opt/AddPage';
-
- { defacto size }
-
- OPTIONSDIALOGPAGE_V0100_SIZE = $18;
- OPTIONSDIALOGPAGE_V0120_SIZE = $28;
-
- { page is only shown when in 'simple' mode }
- ODPF_SIMPLEONLY = 1;
- { page is only shown when in 'expert' mode }
- ODPF_EXPERTONLY = 2;
- { give group box titles a bold font }
- ODPF_BOLDGROUPS = 4;
-
-type
-
- POPTIONSDIALOGPAGE = ^TOPTIONSDIALOGPAGE;
- TOPTIONSDIALOGPAGE = record
- cbSize: int;
- position: int; // position number, lower numbers are top most
- pszTitle: PChar;
- pfnDlgProc: Pointer; // DLGPROC prototype
- pszTemplate: PChar;
- hInstance: THandle;
- hIcon: THandle; // v0.1.0.1+
- pszGroup: PChar; // v0.1.0.1+
- groupPosition: int; // v0.1.0.1+
- hGroupIcon: THandle; // v0.1.0.1+
- flags: DWORD; // v0.1.2.1+
- { if in simple mode the dialog will be cut off AFTER this control ID, 0
- for disable }
- nIDBottomSimpleControl: int; // v0.1.2.1+
- { if in simple mode the dialog will cut off AFTER this control ID, 0 to disable }
- nIDRightSimpleControl: int; // v0.1.2.1+
- { these controls will be hidden in simple mode, pointer to an array of ID's
- must remain valid for the duration of the dialog }
- expertOnlyControls: ^int;
- nExpertOnlyControls: int; // v0.1.2.1+
- end;
-
-const
-
- { sent to pages via WM_NOTIFY when the expert checkbox is clicked, lParam = new state }
- PSN_EXPERTCHANGED = 2;
- { returns true/false }
- PSM_ISEXPERT = ($0400 + 101);
- { returns HFONT used for group box titles }
- PSM_GETBOLDFONT = ($0400 + 102);
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_plugins.inc b/plugins/ShlExt/inc/m_plugins.inc deleted file mode 100644 index 72d5ff69a3..0000000000 --- a/plugins/ShlExt/inc/m_plugins.inc +++ /dev/null @@ -1,70 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_PLUGINS}
-{$DEFINE M_PLUGINS}
-
-const
-
- DEFMOD_PROTOCOLICQ = 1; // removed from v0.3.0.0 alpha
- DEFMOD_PROTOCOLMSN = 2; // removed from v0.1.2.0+
- DEFMOD_UIFINDADD = 3;
- DEFMOD_UIUSERINFO = 4;
- DEFMOD_SRMESSAGE = 5;
- DEFMOD_SRURL = 6;
- DEFMOD_SREMAIL = 7;
- DEFMOD_SRAUTH = 8;
- DEFMOD_SRFILE = 9;
- DEFMOD_UIHELP = 10;
- DEFMOD_UIHISTORY = 11;
- DEFMOD_RNDCHECKUPD = 12;
- DEFMOD_RNDICQIMPORT = 13; // not built in to v0.1.0.1+
- DEFMOD_RNDAUTOAWAY = 14;
- DEFMOD_RNDUSERONLINE = 15;
- DEFMOD_RNDCRYPT = 16; // v0.1.0.1-v0.1.2.0
- DEFMOD_SRAWAY = 17; // v0.1.0.1+
- DEFMOD_RNDIGNORE = 18; // v0.1.0.1+
- DEFMOD_UIVISIBILITY = 19; // v0.1.1.0+, options page only
- DEFMOD_UICLUI = 20; // v0.1.1.0+
- DEFMOD_UIPLUGINOPTS = 21; // v0.1.2.1+
- DEFMOD_PROTOCOLNETLIB = 22; // v0.1.2.2+
-
- DEFMOD_HIGHEST = 22;
-
-
-
- {
- wParam : 0
- lParam : 0
- Affect : Gets an array of modules that the plugins report they want to replace
- Returns: Returns a pointer to an array of ints, with elements 1 or 0,
- indexed by the DEFMOD_* constants, 1 is to mark that the default
- module shouldn't be loaded, see notes
- Notes : this is primarily for use by the core's module initialiser,
- but could also be used by modules that are doing
- naughty things that are very feature-dependent.
- }
- MS_PLUGINS_GETDISABLEDEFAULTARRAY = 'Plugins/GetDisableDefaultArray';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_popup.inc b/plugins/ShlExt/inc/m_popup.inc deleted file mode 100644 index f8d2ea9df9..0000000000 --- a/plugins/ShlExt/inc/m_popup.inc +++ /dev/null @@ -1,222 +0,0 @@ -(*
-===============================================================================
- PopUp plugin
-Plugin Name: PopUp
-Plugin author: hrk, Luca Santarelli, hrk@users.sourceforge.net
-This file has been created by egodust, Sam, egodust@users.sourceforge.net
-===============================================================================
-
-The purpose of this plugin is to give developers a common "platform/interface" to show PopUps. It is born from the source code of NewStatusNotify, another plugin I've made.
-
-Remember that users *must* have this plugin enabled, or they won't get any popup. Write this in the requirements, do whatever you wish ;-)... but tell them!
-===============================================================================
-
--- To use this file you need Windows.pas, m_globaldefs.pas (get it from the CVS under the 'inc' module)
--- To include this in the source, use {$include m_popup.h}
-
-*)
-
-{$ifndef M_POPUP_H}
-{$define M_POPUP_H}
-
-{$ifdef FPC}
- {$PACKRECORDS C}
- {$MODE Delphi}
-{$endif}
-
-const
-
- MAX_CONTACTNAME = 2048;
- MAX_SECONDLINE = 2048;
-
- SM_WARNING = $01; //Triangle icon.
- SM_NOTIFY = $02; //Exclamation mark icon.
-
-type
-
- // for info on what this stuff is, see m_popup.h
-
- PPOPUPDATA = ^TPOPUPDATA;
- TPOPUPDATA = record
- lchContact: HCONTACT;
- lchIcon: THandle;
- lpszContactName: array[0..MAX_CONTACTNAME-1] of Char;
- lpszText: array[0..MAX_SECONDLINE-1] of Char;
- colorBack: COLORREF;
- colorForeText: COLORREF;
- PluginWindowProc: Pointer; // must be a window procedure using stdcall
- PluginData: Pointer;
- end;
-
-type
-
- // for info on what this stuff is, see m_popup.h
-
- PPOPUPDATAEX = ^TPOPUPDATAEX;
- TPOPUPDATAEX = record
- lchContact: HCONTACT;
- lchIcon: THandle;
- lpszContactName: array[0..MAX_CONTACTNAME-1] of Char;
- lpszText: array[0..MAX_SECONDLINE-1] of Char;
- colorBack: COLORREF;
- colorForeText: COLORREF;
- PluginWindowProc: Pointer; // must be a window procedure using stdcall
- PluginData: Pointer;
- iSeconds: int; //Custom delay time in seconds. -1 means "forever", 0 means "default time".
- cZero: array[0..15] of Char; //16 unused bytes which may come useful in the future.
- end;
-
-const
-
-(*
- Creates, adds and shows a popup, given a (valid) POPUPDATA structure pointer.
- wParam = (WPARAM)(*POPUPDATA)PopUpDataAddress
- lParam = 0
- Returns: > 0 on success, 0 if creation went bad, -1 if the PopUpData contained unacceptable values.
- NOTE: it returns -1 if the PopUpData was not valid, if there were already too many popups, if the module was disabled.
- Otherwise, it can return anything else...
-*)
-
- MS_POPUP_ADDPOPUP = 'PopUp/AddPopUp';
-
-(*
- The same, but with a POPUPDATAEX structure pointer.
- wParam = (WPARAM)(*POPUPDATAEX)PopUpDataExAddress
- lParam = 0
-*)
-
- MS_POPUP_ADDPOPUPEX = 'PopUp/AddPopUpEx';
-
-(*
- Returns the handle to the contact associated to the specified PopUpWindow.
- You will probably need to know this handle inside your WNDPROC. Exampole: you want to open the MessageWindow. :-)
- Call MS_POPUP_GETCONTACT on the hWnd you were given in the WNDPROC.
- wParam = (WPARAM)(HWND)hPopUpWindow
- lParam = 0;
- Returns: the HANDLE of the contact. Can return NULL, meaning it's the main contact. -1 means failure.
-*)
-
- MS_POPUP_GETCONTACT = 'PopUp/GetContact';
-
-(*
- wParam = hPopUpWindow
- lParam = PluginDataAddress;
- Returns: the address of the PLUGINDATA structure. Can return NULL, meaning nothing was given. -1 means failure.
- IMPORTANT NOTE: it doesn't seem to work if you do:
- CallService(..., (LPARAM)aPointerToAStruct);
- and then use that struct.
- Do this, instead:
- aPointerToStruct = CallService(..., (LPARAM)aPointerToAStruct);
- and it will work. Just look at the example I've written above (PopUpDlgProc).
-*)
- MS_POPUP_GETPLUGINDATA = 'PopUp/GetPluginData';
-
-(*
- wParam = 0
- lParam = 0
- Returns: 0 if the user has chosen not to have the second line, 1 if he choose to have the second line.
-*)
- MS_POPUP_ISSECONDLINESHOWN = 'PopUp/IsSecondLineShown';
-
-(*
- UM_FREEPLUGINDATA
- wParam = lParam = 0. Process this message if you have allocated your own memory. (i.e.: POPUPDATA.PluginData != NULL)
-*)
- UM_FREEPLUGINDATA = ((*WM_USER*)$400 + $200);
-
-(*
- UM_DESTROYPOPUP
- wParam = lParam = 0. Send this message when you want to destroy the popup, or use the function below.
-*)
- UM_DESTROYPOPUP = ((*WM_USER*)$400 + $201);
-
-(*
- UM_INITPOPUP
- wParam = (WPARAM)(HWND)hPopUpWindow (but this is useless, since I'll directly send it to your hPopUpWindow
- lParam = 0.
- This message is sent to the PopUp when its creation has been finished, so POPUPDATA (and thus your PluginData) is reachable.
- Catch it if you needed to catch WM_CREATE or WM_INITDIALOG, which you'll never ever get in your entire popup-life.
- Return value: if you process this message, return 0. If you don't process it, return 0. Do whatever you like ;-)
-*)
- UM_INITPOPUP = ($400(*WM_USER*) + $202);
-
-(*
- wParam = hPopUpWindow
- lParam = lpzNewText
- returns: > 0 for success, -1 for failure, 0 if the failure is due to second line not being shown. (but you could call PUIsSecondLineShown() before changing the text...)
- Changes the text displayed in the second line of the popup.
-*)
- MS_POPUP_CHANGETEXT = 'PopUp/Changetext';
-
-(*
- This is mainly for developers.
- Shows a warning message in a PopUp. It's useful if you need a "MessageBox" like function, but you don't want a modal window (which will interfere with a DialogProcedure. MessageBox steals focus and control, this one not.
- wParam = lpzMessage
- lParam = 0; Returns: 0 if the popup was shown, -1 in case of failure.
-*)
- MS_POPUP_SHOWMESSAGE = 'PopUp/ShowMessage';
-
-
- (* helper functions, will be inlined on FPC if you have the swithces enabled *)
-
- function PUAddPopup(ppdp: PPOPUPDATA): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := CallService(MS_POPUP_ADDPOPUP, WPARAM(ppdp), 0);
- end;
-
- function PUGetContact(hPopUpWindow: THandle): THandle;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := CallService(MS_POPUP_GETCONTACT, WPARAM(hPopUpWindow), 0);
- end;
-
- function PUGetPluginData(hPopUpWindow: THandle): Pointer;
- {$ifdef FPC}
- inline;
- {$endif}
- var
- dummy: pointer;
- begin
- dummy := nil;
- Int(Result) := CallService(MS_POPUP_GETPLUGINDATA, WPARAM(hPopUpWindow), LPARAM(dummy));
- end;
-
- function PUIsSecondLineShown: BOOL;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Int(Result) := CallService(MS_POPUP_ISSECONDLINESHOWN, 0, 0);
- end;
-
- function PUDeletePopUp(hWndPopUp: THandle): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := SendMessage(hWndPopUp, UM_DESTROYPOPUP, 0, 0);
- end;
-
- function PUChangeText(hWndPopUp: THandle; lpzNewText: PChar): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := CallService(MS_POPUP_CHANGETEXT, WPARAM(hWndPopUp), LPARAM(lpzNewText));
- end;
-
- function PUShowMessage(lpzText: PChar; kind: Byte): int;
- {$ifdef FPC}
- inline;
- {$endif}
- begin
- Result := CallService(MS_POPUP_SHOWMESSAGE, WPARAM(lpzText), LPARAM(kind));
- end;
-
-{$endif}
-
diff --git a/plugins/ShlExt/inc/m_protocols.inc b/plugins/ShlExt/inc/m_protocols.inc deleted file mode 100644 index 90bd12366b..0000000000 --- a/plugins/ShlExt/inc/m_protocols.inc +++ /dev/null @@ -1,180 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_PROTOCOLS}
-{$DEFINE M_PROTOCOLS}
-
-const
-
- ACKTYPE_MESSAGE = 0;
- ACKTYPE_URL = 1;
- ACKTYPE_FILE = 2;
- ACKTYPE_CHAT = 3;
- ACKTYPE_AWAYMSG = 4;
- ACKTYPE_AUTHREQ = 5;
- ACKTYPE_ADDED = 6;
- ACKTYPE_GETINFO = 7;
- ACKTYPE_SETINFO = 8;
- ACKTYPE_LOGIN = 9;
- ACKTYPE_SEARCH = 10;
- ACKTYPE_NEWUSER = 11;
- ACKTYPE_STATUS = 12;
- ACKTYPE_CONTACTS = 13; //send/recv of contacts
-
- ACKRESULT_SUCCESS = 0;
- ACKRESULT_FAILED = 1;
- //'in progress' result codes:
- ACKRESULT_CONNECTING = 100;
- ACKRESULT_CONNECTED = 101;
- ACKRESULT_INITIALISING = 102;
- ACKRESULT_SENTREQUEST = 103; // waiting for reply...
- ACKRESULT_DATA = 104; // blob of file data sent/recved, or search result
- ACKRESULT_NEXTFILE = 105; // file transfer went to next file
- ACKRESULT_FILERESUME = 106; // a file is about to be received, see PS_FILERESUME
- ACKRESULT_DENIED = 107; // a file send has been denied (0.3a + only)
-
- // for PROTOCOLDESCRIPTOR.type
-
- PROTOTYPE_PROTOCOL = 1000;
- PROTOTYPE_ENCRYPTION = 2000;
- PROTOTYPE_FILTER = 3000;
- PROTOTYPE_TRANSLATION = 4000;
- PROTOTYPE_OTHER = 10000;//avoid using this if at all possible
-
-type
-
- PCCSDATA = ^TCCSDATA;
- TCCSDATA = record
- hContact: THandle;
- szProtoService: PChar; // a PS_* constant
- wParam: WPARAM;
- lParam: LPARAM;
- end;
-
- PACKDATA = ^TACKDATA;
- TACKDATA = record
- cbSize: int;
- szModule: PChar; // the name of the protocol module which initiated this ack
- hContact: THandle;
- type_: int; // an ACKTYPE_* constant
- result_: int; // an ACKRESULT_* constant
- hProcess: THandle; // caller defined seq, I mean process code
- lParam: LPARAM; // caller defined data
- end;
-
- // when type=ACKTYPE_FILE and (result=ACKRESULT_DATA or result=ACKRESULT_FILERESUME)
-
- PPROTOFILETRANSFERSTATUS = ^TPROTOFILETRANSFERSTATUS;
- TPROTOFILETRANSFERSTATUS = record
- cbSize: int;
- hContact: THandle;
- sending: int; // true if sending, false if receiving
- files: PChar; // pointer to an array of pchar's
- totalFiles: int;
- currentFileNumber: int;
- totalBytes: LongInt;
- totalProgress: LongInt;
- workingDir: PChar;
- currentFile: PChar;
- currentFileSize: LongInt;
- currentFileProgress: LongInt;
- currentFileTime: LongInt; // UNIX time
- end;
-
- // for registering a protocol, enumeration
-
- PPROTOCOLDESCRIPTOR = ^TPROTOCOLDESCRIPTOR;
- TPROTOCOLDESCRIPTOR = record
- cbSize: int;
- szName: PChar; // unique name of module
- type_: int; // a PROTOTYPE_* constant
- end;
-
-const
-
- {
- wParam : 0
- lParam : Pointer to an initalised CSSDATA structure
- Affect : Send a general request thru the protocol chain for a contact
- Return : the return value documented in the PS_* def (m_protosvc.inc)
- }
- MS_PROTO_CALLCONTACTSERVICE = 'Proto/CallContactService';
-
- {
- wParam : 0
- lParam : Pointer to an initalised TACKDATA structure
- Affect : a general 'ack', see notes
- Notes : Just because defs are here doesn't mean they will be sent
- read the docs for the function you are calling to see what
- replies you will get.
- }
- ME_PROTO_ACK = 'Proto/Ack';
-
- {
- wParam : pointer to an int to store number of protocols
- lParam : Pointer to an an array of PPROTOCOLDESCRIPTOR pointers
- Affect : Enumerate the currently running protocols, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : Neither wParam/lParam maybe NULL(0), the list returned by
- this service is the protocol modules currently installed
- and running, it is not a complete list of protocols that have
- ever been installed.
- -
- A protocol module does not have to be a protocol running thru
- the internet, it can be a vast number of things
- }
- MS_PROTO_ENUMPROTOCOLS = 'Proto/EnumProtocols';
-
- {
- wParam : 0
- lParam : Pointer to null terminated string containing protocol name
- Affect : Determines if a protocol is running or not.
- Returns: A pointer to the PPROTOCOLDESCRIPTOR if the protocol is loaded
- or NULL(0) if it isn't
- }
- MS_PROTO_ISPROTOCOLLOADED = 'Proto/IsProtocolLoaded';
-
- {
- wParam : HCONTACT
- lParam : Pointer to a null terminated string containing a name
- Affect : Determine whether the given contact has the given protocol
- in it's chain.
- Returns : 0 if the protocol isn't in the chain, [non zero] if it is
- }
- MS_PROTO_ISPROTOONCONTACT = 'Proto/IsProtoOnContact';
-
- {
- wParam : HCONTACT
- lParam : 0
- Affect : Gets the network-level protocol associated with a contact
- Returns: a PChar pointing to the ASCIIZ name of the protocol or NULL(0)
- if the contact has no protocol, There's no need to dispsose
- the returned string.
- -
- This is the name of the module that actually accesses the network
- for that contact.
- }
- MS_PROTO_GETCONTACTBASEPROTO = 'Proto/GetContactBaseProto';
-
-{$ENDIF}
\ No newline at end of file diff --git a/plugins/ShlExt/inc/m_protomod.inc b/plugins/ShlExt/inc/m_protomod.inc deleted file mode 100644 index 8bf245316c..0000000000 --- a/plugins/ShlExt/inc/m_protomod.inc +++ /dev/null @@ -1,105 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_PROTOMOD}
-{$DEFINE M_PROTOMOD}
-
- {$ifndef M_PROTOCOLS}
- {$include m_protocols.inc}
- {$endif}
-
-const
-
- {
- wParam : 0
- lParam : Pointer to a initalised TPROTOCOLDESCRIPTOR structure
- Affect : Register a protocol module, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : This service MUST be called from your module's Load() function
- TPROTOCOLDESCRIPTOR.type can be a value other than PROTOTYPE_*
- which are used to provide a more precise positioning information
- for the contact protocol lists.
- -
- Relative values to the constants can be given, but this MUST NOT
- be done for PROTOTYPE_PROTOCOL.
- }
- MS_PROTO_REGISTERMODULE = 'Proto/RegisterModule';
-
- {
- wParam : HCONTACT
- lParam : protocol_name_string
- Affect : Add the given protocol module to the chain for a contact, see notes
- Returns: 0 success, [non zero] on failure
- Notes : The module is added to the correct positioning according to it's
- registered type.
- }
- MS_PROTO_ADDTOCONTACT = 'Proto/AddToContact';
-
- {
- wParam : HCONTACT
- lParam : protocol_name_string
- Affect : Remove the given protocol name from the chain for the given contact
- Returns: 0 on success, [non zero] on failure
- }
- MS_PROTO_REMOVEFROMCONTACT = 'Proto/RemoveFromContact';
-
- { see m_globaldefs.pas for CreateProtoServiceFunction }
-
- {
- wParam : wParam [arg]
- lParam : lParam [arg]
- Affect : Call the next service in the chain for the send operation, see notes
- Return : Return value should be returned by CallService(MS_PROTO_CHAINSEND,wParam,lParam)
- Notes : wParam MUST remain untouched, lParam is a pointer to a CSSDATA structure
- and can be modified or copid if needed.
- wParam and lParam should be the values passed to your service,
- typically your service should return ASAP.
- }
- MS_PROTO_CHAINSEND = 'Proto/ChainSend';
-
- {
- wParam : wParam [arg]
- lParam : lParam [arg]
- Affect : Call the next service in the chain in this receive operation, see notes
- Return : Return value should be returned by CallService(MS_PROTO_CHAINRECV,wParam,lParam)
- Notes : wParam MUST remain untouched, lParam is a pointer to a CSSDATA structure
- and can be modified or copied if needed.
- wParam and lParam should be the values passed to your service,
- typically your service should return ASAP.
- -
- MS_PROTO_CHAINRECV is thread safe since 0.1.2.0 -- calls
- are translated to the main thread and passed from there.
- }
- MS_PROTO_CHAINRECV = 'Proto/ChainRecv';
-
- {
- wParam : 0
- lParam : Pointer to an initalised ACKDATA
- Affect : Broadcast a ME_PROTO_ACK event, see notes
- Returns: The return value of the NotifyEventHooks() call
- Notes : ME_PROTO_ACK is completely thread safe since 01.2.0
- see notes in core/modules.h under NotifyEventHooks()
- }
- MS_PROTO_BROADCASTACK = 'Proto/BroadcastAck';
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_protosvc.inc b/plugins/ShlExt/inc/m_protosvc.inc deleted file mode 100644 index 9fde8268bb..0000000000 --- a/plugins/ShlExt/inc/m_protosvc.inc +++ /dev/null @@ -1,753 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_PROTOSVC}
-{$DEFINE M_PROTOSVC}
-
-{<</
- none of these services should be used on there own (i.e. using CallService(), etc)
- hence the PS_ prefix, instead use the services exposed in m_protocols.inc
-
- these should be called with CallProtoService which prefixes the protocol module
- name before calling.
- -
- Deleting contacts from protocols that store the contact list on the server:
- If a contact is deleted while the protocol is online, it is expected that the
- protocol will have hooked me_db_contact_deleted and take the appropriate
- action by itself.
- If a contact is deleted while the protocol is offline, the contact list will
- display a message to the user about the problem, and set the byte setting
- "CList"/"Delete" to 1. Each time such a protocol changes status from offline
- or connecting to online the contact list will check for contacts with this
- flag set and delete them at that time. Your hook for me_db_contact_deleted
- will pick this up and everything will be good.
-/>>}
-
-const
-
- PFLAGNUM_1 = $1;
- PF1_IMSEND = $00000001; // supports IM sending
- PF1_IMRECV = $00000002; // supports IM receiving
- PF1_IM = (PF1_IMSEND or PF1_IMRECV);
- PF1_URLSEND = $00000004; // supports separate URL sending
- PF1_URLRECV = $00000008; // supports separate URL receiving
- PF1_URL = (PF1_URLSEND or PF1_URLRECV);
- PF1_FILESEND = $00000010; // supports file sending
- PF1_FILERECV = $00000020; // supports file receiving
- PF1_FILE = (PF1_FILESEND or PF1_FILERECV);
- PF1_MODEMSGSEND = $00000040; // supports broadcasting away messages
- PF1_MODEMSGRECV = $00000080; // supports reading others' away messages
- PF1_MODEMSG = (PF1_MODEMSGSEND or PF1_MODEMSGRECV);
- PF1_SERVERCLIST = $00000100; // contact lists are stored on the server, not locally. See notes below
- PF1_AUTHREQ = $00000200; // will get authorisation requests for some or all contacts
- PF1_ADDED = $00000400; // will get 'you were added' notifications
- PF1_VISLIST = $00000800; // has an invisible list
- PF1_INVISLIST = $00001000; // has a visible list for when in invisible mode
- PF1_INDIVSTATUS = $00002000; // supports setting different status modes to each contact
- PF1_EXTENSIBLE = $00004000; // the protocol is extensible and supports plugin-defined messages
- PF1_PEER2PEER = $00008000; // supports direct (not server mediated) communication between clients
- PF1_NEWUSER = $00010000; // supports creation of new user IDs
- PF1_CHAT = $00020000; // has a realtime chat capability
- PF1_INDIVMODEMSG = $00040000; // supports replying to a mode message request with different text depending on the contact requesting
- PF1_BASICSEARCH = $00080000; // supports a basic user searching facility
- PF1_EXTSEARCH = $00100000; // supports one or more protocol-specific extended search schemes
- PF1_CANRENAMEFILE = $00200000; // supports renaming of incoming files as they are transferred
- PF1_FILERESUME = $00400000; // can resume broken file transfers, see PS_FILERESUME below
- PF1_ADDSEARCHRES = $00800000; // can add search results to the contact list
- PF1_CONTACTSEND = $01000000; // can send contacts to other users
- PF1_CONTACTRECV = $02000000; // can receive contacts from other users
- PF1_CONTACT = (PF1_CONTACTSEND or PF1_CONTACTRECV);
- PF1_CHANGEINFO = $04000000; // can change our user information stored on server
- PF1_SEARCHBYEMAIL = $08000000; // supports a search by e-mail feature
- PF1_USERIDISEMAIL = $10000000; // set if the uniquely identifying field of the network is the e-mail address
- PF1_SEARCHBYNAME = $20000000; // supports searching by nick/first/last names
- PF1_EXTSEARCHUI = $40000000; // has a dialog box to allow searching all the possible fields
- PF1_NUMERICUSERID = $80000000; // the unique user IDs for this protocol are numeric
-
- PFLAGNUM_2 = 2; // the status modes that the protocol supports
- PF2_ONLINE = $00000001; // an unadorned online mode
- PF2_INVISIBLE = $00000002;
- PF2_SHORTAWAY = $00000004; // Away on ICQ, BRB on MSN
- PF2_LONGAWAY = $00000008; // NA on ICQ, Away on MSN
- PF2_LIGHTDND = $00000010; // Occupied on ICQ, Busy on MSN
- PF2_HEAVYDND = $00000020; // DND on ICQ
- PF2_FREECHAT = $00000040;
- PF2_OUTTOLUNCH = $00000080;
- PF2_ONTHEPHONE = $00000100;
-
- PFLAGNUM_3 = 3; //the status modes that the protocol supports
- //away-style messages for. Uses the PF2_ flags.
- PFLAG_UNIQUEIDTEXT = 100; //returns a static buffer of text describing the unique field by which this protocol identifies users (already translated), or NULL
-
- PFLAG_MAXCONTACTSPERPACKET = 200; //v0.1.2.2+: returns the maximum number of contacts which can be sent in a single PSS_CONTACTS.
-
- PFLAGNUM_4 = 4; // v0.3+: flag asking a protocol plugin how auths are handled
- PF4_FORCEAUTH = $00000001; // protocol has to send auth's for things to work
- PF4_FORCEADDED = $00000002; // protocol has to tell people that they were added (otherwise things don't work)
- PF4_NOCUSTOMAUTH = $00000004; // protocol can't send a custom message while asking others for auth
-
- PFLAG_UNIQUEIDSETTING = 300; // v0.3+: returns the DB setting name (e.g. szProto=ICQ, szSetting=UIN) that has the ID which makes this user unique on that system (0.3a ONLY), the string is statically allocated so no need to free()
-
- // for PS_SETSTATUS
-
- LOGINERR_WRONGPASSWORD = 1;
- LOGINERR_NONETWORK = 2;
- LOGINERR_PROXYFAILURE = 3;
- LOGINERR_BADUSERID = 4;
- LOGINERR_NOSERVER = 5;
- LOGINERR_TIMEOUT = 6;
- LOGINERR_WRONGPROTOCOL = 7;
-
- // flag for PS_ADDTOLIST
-
- PALF_TEMPORARY = 1; // add the contact temporarily and invisibly, just to get user info or something
-
- // flags for PS_GETINFO
-
- SGIF_MINIMAL = 1; // get only the most basic information. This should
- // contain at least a Nick and e-mail.
-
- // for PSR_MESSAGE
-
- PREF_CREATEREAD = 1; // create the database event with the 'read' flag set
-
- // for PS_FILERESUME
-
- FILERESUME_OVERWRITE= 1;
- FILERESUME_RESUME = 2;
- FILERESUME_RENAME = 3;
- FILERESUME_SKIP = 4;
-
-type
-
- PPROTOSEARCHRESULT = ^TPROTOSEARCHRESULT;
- TPROTOSEARCHRESULT = record
- cbSize: int;
- nick: PChar;
- firstName: PChar;
- lastName: PChar;
- email: PChar;
- reserved: array [0..15] of Byte;
- // Protocols may extend this structure with extra members at will and supply
- // a larger cbSize to reflect the new information, but they must not change
- // any elements above this comment
- // The 'reserved' field is part of the basic structure, not space to
- // overwrite with protocol-specific information.
- // If modules do this, they should take steps to ensure that information
- // they put there will be retained by anyone trying to save this structure.
- end;
-
- PPROTOSEARCHBYNAME = ^TPROTOSEARCHBYNAME;
- TPROTOSEARCHBYNAME = record
- pszNick: PChar;
- pszFirstName: PChar;
- pszLastName: PChar;
- end;
-
- PPROTORECVEVENT = ^TPROTORECVEVENT;
- TPROTORECVEVENT = record
- flags: DWORD;
- timestamp: DWORD;
- szMessage: PChar;
- lParam: LPARAM;
- end;
-
- PPROTORECVFILE = ^TPROTORECVFILE;
- TPROTORECVFILE = record
- flags: DWORD;
- timestamp: DWORD; // unix time
- szDescription: PChar;
- pFiles: PChar; // pointer to an array of pchar's
- lParam: LPARAM;
- end;
-
- PPROTOFILERESUME = ^TPROTOFILERESUME;
- TPROTOFILERESUME = record
- action: int; // FILERESUME_* flag
- szFilename: PChar; // full path, only valid if action=FILERESUME_RENAME
- end;
-
-const
-
- {
- wParam : PFLAGNUM_* (see above)
- lParam : 0
- Affects: Returns a bitfield for settings corresponding to flag number, see notes
- Returns: a bitfield of supported features -- or 0 if flag_num is not supported
- Notes : this checks what sort of things are actively supported by a protocol
- module
- }
- PS_GETCAPS = '/GetCaps';
-
- {
- wParam : cchName
- lParam : Pointer to a buffer to fill with human-readable name
- Affect : Get a human-readable name for the protocol, see notes
- Result : 0 on success, [non zero] on failure
- Notes : Should be translated before being returned, cchName
- has the size of the buffer, example strings: "ICQ", "AIM"
- }
- PS_GETNAME = '/GetName';
-
- {
- wParam : whichIcon
- lParam : 0
- Affect : Loads one of the protocol-sspecific icons
- Returns: the HICON or NULL on failure, the returned icon
- must be DestroyIcon()ed, the UI should overlay
- the online icon with further UI-specified icon to
- repressent the exact status mode.
- }
- PLI_PROTOCOL = $1; // An icon representing the protocol (eg the multicoloured flower for ICQ)
- PLI_ONLINE = $2; // Online state icon for that protocol (eg green flower for ICQ)
- PLI_OFFLINE = $3; // Offline state icon for that protocol (eg red flower for ICQ)
- PLIF_LARGE = $0; // Or with one of the above to get the large (32x32 by default) icon
- PLIF_SMALL = $10000; // Or with one of the above to get the small (16x16 by default) icon
-
- PS_LOADICON = '/LoadIcon';
-
- {
- wParam : status_mode
- lParam : Pointer to a null terminated string containing message
- Affect : Sets the status mode specific message for the user, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : This service is not available unless PF1_MODEMSGSEND is set,
- and PF1_INDIVMODEMSG is *not* set.
- If PF1_INDIVMODEMSG is set, then see PSS_AWAYMSSG for details
- of operations of away messages.
- -
- Protocol modules smust support lParam=NULL, it may eithere mean
- to use an empty message or (preferably) not to reply at all to
- any requests.
- }
- PS_SETAWAYMSG = '/SetAwayMsg';
-
- {
- wParam : newMode from statusmodes.inc
- lParam : 0
- Affect : Change the protocol's status mode, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : Will send an ack with :
- type=ACKTYPE_SUCCESS, result=ACKRESULT_SUCCESS, hProcess=previousMode, lParam=newMode
- -
- when the change completes. This ack is sent for all changes, not
- just ones caused by calling this function.
- -
- NewMode can be ID_STATUS_CONNECTING<=newMode<ID_STATUS_CONNECTING+
- MAX_CONNECT_RETRIES to signify that it's connecting and it's the nth retry.
- -
- Protocols are initially always in offline mode, if a protocol
- doesn't support a specific status mode, it should pick the closest
- ones that it does support, and change to that.
-
- If a protocol has to switch from offline mode to online (or a substate
- of online, like away) then it should report any errors in the
- form of an additional ack :
-
- type=ACKTYPE_LOGIN, result=ACKRESULT_FAILURE, hProcess=NULL, lParam=LOGINERR_*
-
- SetStatus() is called when a protocol module is first loaded
- with newMode=ID_STATUS_ONLINE.
- -
- Protocols can define their own LOGINERR_* starting at $1000, see
- LOGINERR_* above
- }
- PS_SETSTATUS = '/SetStatus';
-
- {
- wParam : 0
- lParam : 0
- Affect : Get the status mode that a protocol is currently in, see notes
- Returns: The current status mode
- Notes : Only protocol modules need to implement this, non network level
- protocol modules do not need to (but if you register as a protocol
- you need to, Miranda will GPF otherwise)
- }
- PS_GETSTATUS = '/GetStatus';
-
- {
- wParam : HDBEVENT
- lParam : 0
- Affect : allow 'somebody' to add the user to their contact list, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : Auth request come in the form of an event added to the database
- for the NULL(0) user, the form is:
- -
- protocolSpecific: DWORD;
- nick, firstname, lastName, e-mail, requestReason: ASCIIZ;
- -
- HDBEVENT musts be the handle of such an event, one or more
- fields may be empty if the protocol doesn't support them
- }
- PS_AUTHALLOW = '/Authorize';
-
- {
- wParam : HDBEVENT
- lParam : Pointer to a null terminated string containing the reason, see notes
- Affect : Deny an authorisation request
- Returns: 0 on success, [non zero] on failure
- Notes : Protocol modules must be able to cope with lParam=NULL(0)
- }
- PS_AUTHDENY = '/AuthDeny';
-
- {
- wParam : 0
- lParam : Pointer to a null terminated string containing an ID to search for
- Affect : Send a basic search request, see notes
- Returns: A handle to the search request or NULL(0) on failure
- Notes : All protocols identify users uniquely by a single field
- this service will search by that field.
- -
- All search replies (even protocol-spec extended searches)
- are replied by a series of ack's,-
- -
- Result acks are a series of:
- type=ACKTYPE_SEARCH, result=ACKRESULT_DATA, lParam=Pointer to a TPROTOSEARCHRESULT structure
- -
- ending ack:
- type=ACKTYPE_SEARCH, result=ACKRESULT_SUCCESS, lParam=0
- -
- The pointers in the structure are not guaranteed to be
- valid after the ack is complete.
- -
- The structure to reply with search results can be extended
- per protocol basis (see below)
-
- }
- PS_BASICSEARCH = '/BasicSearch';
-
- {
- wParam : 0
- lParam : Pointer to a NULL terminated string containing the e-mail to search for
- Affect : Search for user(s) by e-mail address, see notes
- Returns: A HANDLE to the search, or NULL(0) on failure
- Notes : Results are returned as for PS_BASICSEARCH, this service
- is only available if the PF1_USERIDISEMAIL flag is set for caps --
- -
- This service with the above service should be mapped to the same
- function if the aforementioned flag is set.
- Version: v0.1.2.1+
- }
- PS_SEARCHBYEMAIL = '/SearchByEmail';
-
- {
- wParam : 0
- lParam : Pointer to a TPROTOSEARCHBYNAME structure
- Affect : Search for users by name, see notes
- Returns: Handle to the search, NULL(0) on failure
- Notes : this service is only available, if PF1_SEARCHBYNAME capability is set.
- Results are returned in the same manner as PS_BASICSEEARCH
- Version: v0.1.2.1+
- }
- PS_SEARCHBYNAME = '/SearchByName';
-
- {
- wParam : 0
- lParam : Handle to window owner
- Affect : Create the advanced search dialog box, see notes
- Returns: A window handle, or NULL(0) on failure
- Notes : this service is only available if PF1_EXTSEARCHUI capability is
- set, advanced search is very protocol-spec'd so it is left to
- the protocol itself to supply a dialog containing the options,
- this dialog should not have a titlebar and contain only search
- fields. the rest of the UI is supplied by Miranda.
- -
- The dialog should be created with CreateDialog() or it's kin
- and still be hidden when this function returns,
- -
- The dialog will be destroyed when the find/add dialog is closed
- Version: v0.1.2.1+
- }
- PS_CREATEADVSEARCHUI= '/CreateAdvSearchUI';
-
- {
- wParam : 0
- lParam : Handle to advanced search window handle
- Affect : Search using the advanced search dialog, see notes
- Returns: A handle or NULL(0) on failure
- Notes : Results are returned in the same manner as PS_BASICSEARCH,
- this service is only available if PF1_EXTSEARCHUI capability is set
- Version: v0.1.2.1+
- }
- PS_SEARCHBYADVANCED = '/SearchByAdvanced';
-
- {
- wParam : flags
- lParam : Pointer to a TPROTOSEARCHRESULT structure
- Affect : Adds a search result to the contact list, see notes
- Returns: A handle to the new contact (HCONTACT) or NULL(0) on failure
- Notes : The pointer MUST be a result returned by a search function
- since there maybe extra protocol-spec data required by the protocol.
- -
- the protocol module should not allow duplicate contains to be added,
- but if such a request *is* received it should return a HCONTACT
- to the original user,
- -
- If flags is PALF_TEMPORARY set, the contact should be added
- temorarily and invisiblely, just to get the user info (??)
- -
- }
- PS_ADDTOLIST = '/AddToList';
-
- {
- wParam : MAKEWPARAM(flags, iContact)
- lParam : HDBEVENT
- Affects: Add a contact to the contact list given an auth/added/contacts events, see notes
- Returns: A HCONTACT or NULL(0) on failure
- Notes : HDBEVENT must be either EVENTTYPE_AUTHREQ or EVENTTYPE_ADDED
- flags are the same as PS_ADDTOLIST,
- -
- iContacts is only used for contacts vents, it is 0-based index
- of the contacts in the event to add, there's no way to add two or more
- contacts at once, you should just call this as many times as needed.
- }
- PS_ADDTOLISTBYEVENT = '/AddToListByEvent';
-
- {
- wParam : InfoType
- lParam : Pointer to InfoData
- Affect : Changes user details as stored on the server, see notes
- Returns: A Handle to the change request or NULL(0) on failure
- Notes : the details stored on the server are very protocol spec'd
- so this service just supplies an outline for protocols to use.
- See protocol-specific documentation for what infoTypes are available
- and what InfoData should be for each infoTypes.
- -
- Sends an ack type=ACKTYPE_SETINFO, result=ACKRESULT_SUCCESS/FAILURE, lParam=0
- -
- This description just leaves me cold.
- Version: v0.1.2.0+
- }
- PS_CHANGEINFO = '/ChangeInfo';
-
- {
- wParam : HFILETRANSFER
- lParam : Pointer to a initalised TPROTOFILERESUME
- Affect : Informs the protocol of the user's chosen resume behaviour, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : If the protocol supports file resume (caps: PF1_FILERESUME) then before
- each file receive begins it will broadcast an ack with :
-
- type=ACKTYPE_FILE, result=ACKRESULT_RESUME, hProcess=hFileTransfer,
- lParam = TPROTOFILETRANSFERSTATUS.
-
- If the UI processes this ack it must return a [non zero] valuee from it's
- hook, it all the hooks complete without returning [non zero] then the
- protocol will assume that no resume UI was available and will continue
- to receive the file with a default behaviour (default: overwrite)
- -
- If a hook does return [non zero] then that UI MUST call this service,
- PS_FILERESUME at some point.
- When the protocol module receives this call it will proceed wit the
- file recieve usingg the given information.
- -
- Having sasid that, PS_FILERESUME MUST be called, it is also
- acceptable to completely abort the transfer instead, i.e. the file
- exists locally and the user doesn't want to overwrite or resume or
- reget.
- Version: v0.1.2.2+
- }
- PS_FILERESUME = '/FileResume';
-
- // these should be called with CallContactService()
-
- {<</
- !IMPORTANT!
- wParam, lParam data expected declarations should be treated with
- one level of indirection, where it says (CCSDATA: Yes)
- should be :
-
- What you *actually* get in the service:
-
- wParam = 0
- lParam = pCCSDATA
-
- CCSDATA contains the ..wParam, ..lParam, hContact data declared with each service,
- so the wParam, lParam passed does not contain the data itself, but lParam
- contains a pointer to a structure which contains the data.
-
- />>}
-
- {
- CCSDATA: Yes
- wParam : flags
- Param : 0
-
- Affect : Updates a contact's details from the server, see notes
- Returns: 0 on success, [non zero] on failure
- Notes :
-
- flags which may have SGIF_MINIMAL set to only get
- "basic" information, such as nickname, email address.
-
- PCCSDATA(lParam)^.hContact has the HCONTACT handle to get user
- information for.
-
- Will update all the information in the database and then
- send acks with :
-
- type=ACKTYPE_GETINFO, result=ACKRESULT_SUCCESS, hProcess=nReplies, lParam=thisReply
- -
- Since some protocol do not allow the module to tell when it has
- got all the information so it can send a final ack, one
- ack will be sent after each chunk of data has been received,
- -
- nReplies contains the number of distinct acks
- that will be sent to get all the information, 'thisReply'
- is the zero based index of this ack.
- When thisReply=0 the minimal information has just been received,
- all other numbering is arbitrary.
-
- }
- PSS_GETINFO = '/GetInfo';
-
- {
- CCSDATA: Yes
- wParam : flags
- lParam : Pointer to a null terminated string
- Affect : Send an instant message
- Returns: an hProcess corresponding to an ACK which will be sent after
- the hProcess.
- Notes: type=ACKTYPE_MESSAGE, result=ACKRESULT_SUCCESS/FAILURE, lParam = 0
- -
- here's the deal, you must return a 'seq' from this service
- which you have to ack when the message actually get's sent,
- or send a fake ack sometime soon if you can't find out if the message
- was successfully received with the protocol that you're using.
- -
- this event is NOT added to the database automatically.
- }
- PSS_MESSAGE = '/SendMsg';
-
- {
- CCSDATA: Yes
- wParam : flags
- lParam : null terminated string to the URL, see notes
- Affect : Send a URL message, see notes
- Returns: A hProcess which will be ack'd later
- Notes : lParam may contain TWO strings, the first for URL, the second for
- description, in the format :
- <url>#0<desc>#0 or <url>#0#0
- Will send an ack for hProcess when the URL actually gets sent
- type=ACKTYPE_URL, result=ACKRESULT_SUCCESS/FAILURE, lParam=0
- -
- protocol modules are free to define flags starting at $10000
- -
- The event will *not* be added to the database automatically
- }
- PSS_URL = '/SendUrl';
-
- {
- CCSDATA: Yes
- wParam : MAKEWPARAM(flags)
- lParam : Pointer to hContactsList
- Affect : Send a set of contacts, see notes
- Returns: A hProcess which will be ack, NULL(0) on failure
- Notes : hContactsList is an array of nContacts handles to contacts,
- if this array includes one or more contains that can not be transferred
- using this protocol the function will fail.
- -
- Will send an ack when the contacts actually get sent:
-
- type=ACKTYPE_CONTACTS, result=ACKRESULT_SUCCESS/FAILURE, lParam=0
- -
- No flags have ben defined yet,
- -
- The event will *not* be added to the database automatically
- }
- PSS_CONTACTS = '/SendContacts';
-
- {
- CCSDATA: Yes
- wParam : 0
- lParam : 0
- Affect : Send a request to retrieve HCONTACT's mode message, see notes
- Returns: a hProcess which will be ack'd later, NULL(0) on failure
- Notes : the reply will come in a form of an ack :
-
- type=ACKTYPE_AWAYMSG, result=ACKRESULT_SUCCESS/FAILURE,
- lParam=pointer to a null terminated string the containing message
- }
- PSS_GETAWAYMSG = '/GetAwayMsg';
-
- {
- CCSDATA: Yes
- wParam : hProcess
- lParam : pointer to a buffer to fill with away message to reply with
- Affect : Sends an away message reply to a user, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : This service must only be called is caps has PF1_MODEMSGSEND set
- as well as PF1_INDIVMODEMSG otherwise PS_SETAWAYMESSAGE should
- be used.
- -
- Reply will be sent in the form of an ack :
-
- type=ACKTYPE_AWAYMSG, result=ACKRESULT_SENTREQUEST, lParam=0
- }
- PSS_AWAYMSG = '/SendAwayMsg';
-
- {
- CCSDATA: Yes
- wParam : status_mode
- lParam : Pointer to a TPROTORECVEVENT structure
- Affect : An away message reply has been received
- }
- PSR_AWAYMSG = '/RecvAwayMsg';
-
- {
- CCSDATA: Yes
- wParam : status_mode
- lParam : 0
- Affect : Set the status mode the user will appear in to a user, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : If status_mode = 0 then revert to normal state for the user,
- ID_STATUS_ONLINE is possible if PF1_VISLIST
- ID_STATUS_ONLINE is possible if PF1_INDIVSTATUS
- }
- PSS_SETAPPARENTMODE = '/SetApparentMode';
-
- // only valid if caps support IM xfers
-
- {
- CCSDATA: Yes
- wParam : HTRANSFER
- lParam : null terminated string containing the path
- Affect : Allow a file transfer to begin, see notes
- Returns: A handle to the transfer to be used from now on.
- Notes : If the path does not point to a directory then:
- if a single file is being transfered and the protocol supports
- file renaming (PF1_CANRENAMEFILE) then the file is given
- this name, othewise the file is removed and file(s) are placed
- into the resulting directory.
- -
- File transfers are marked by a EVENTTYPE_FILE added to the database.
- The format is :
- hTransfer: DWORD
- filename(s), description: ASCIIZ
- }
- PSS_FILEALLOW = '/FileAllow';
-
- {
- CCSDATA: Yes
- wParam : HTRANSFER
- lparam : Pointer to a buffer to be filled with reason
- Affect : Refuses a file transfer request
- Returns: 0 on success, [non zero] on failure
- }
- PSS_FILEDENY = '/FileDeny';
-
- {
- CCSDATA: Yes
- wParam : HTRANSFER
- lParam : 0
- Affect : Cancel an in-progress file transfer
- Returns: 0 on success, [non zero] on failure
- }
- PSS_FILECANCEL = '/FileCancel';
-
- {
- CCSDATA: Yes
- wParam : null terminated string containing description
- lParam : pointer to an array of pchar's containing file paths/directories
- Affect : Start a file(s) send, see notes
- Returns: A HTRANSFER handle on success, NULL(0) on failur
- Notes : All notifications are done thru acks :
- -
- type=ACKTYPE_FILE, if result=ACKRESULT_FAILED then
- lParam=null terminated string containing reason
- }
- PSS_FILE = '/SendFile';
-
- // Receiving Services
- {>>/
- Receiving Services:
- Before a message is sent to /RecvMessage it goes through a MS_PROTO_CHAINRECV
- which allows any other module to change data (for decryption, etc),
- this then reaches /RecvMessage.
-
- This does not have to be the same structure/memory contained within that
- structure that started the chain call.
-
- /RecvMessage adds the event to the database, any other modules who
- are interested in what message the user will see should hook at this point.
- />>}
-
- {
- CCSDATA: Yes
- wParam : 0
- lParam : Pointer to a TPROTORECVEVENT
- Affect : An instant message has beeen received, see notes
- Returns: 0
- Notes : lParam^.lParam^.szMessage has the message, see structure above
- stored as DB event EVENTTYPE_MESSAGE, blob contains message
- string without null termination.
- }
- PSR_MESSAGE = '/RecvMessage';
-
- {
- CCSDATA: Yes
- wParam : 0
- lParam : Pointer to a TPROTORECVEVENT, see notes
- Affect : A URL has been received
- Notes : szMessage is encoded the same as PSS_URL
- -
- Stored in the database : EVENTTYPE_URL, blob contains message
- without null termination
- }
- PSR_URL = '/RecvUrl';
-
- {
- CCSDATA: Yes
- wParam : 0
- lParam : Pointer to a TPROTORECVEVENT
- Affect : Contacts have been received, see notes
- Notes : pre.szMessage is actually a PROTOSEARCHRESULT list
- pre.lParam is the number of contains in that list.
- -
- PS_ADDTOLIST can be used to add contacts to the list
- -
- repeat [
- ASCIIZ userNick
- ASCIIZ userId
- ]
- userNick should be a human-readable description of the user. It need not
- be the nick, or even confined to displaying just one type of
- information.
- userId should be a machine-readable representation of the unique
- protocol identifying field of the user. Because of the need to be
- zero-terminated, binary data should be converted to text.
- Use PS_ADDTOLISTBYEVENT to add the contacts from one of these to the list.
- }
- PSR_CONTACTS = '/RecvContacts';
-
- {
- CCSDATA: Yes
- wParam : 0
- lParam : Pointer to a TPROTORECVFILE
- Affect : File(s) have been received
- }
- PSR_FILE = '/RecvFile';
-
-{$ENDIF}
-
diff --git a/plugins/ShlExt/inc/m_skin.inc b/plugins/ShlExt/inc/m_skin.inc deleted file mode 100644 index aee28ae4d9..0000000000 --- a/plugins/ShlExt/inc/m_skin.inc +++ /dev/null @@ -1,120 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-{$IFNDEF M_SKIN}
-{$DEFINE M_SKIN}
-
-const
-
- // event icons
-
- SKINICON_EVENT_MESSAGE = 100;
- SKINICON_EVENT_URL = 101;
- SKINICON_EVENT_FILE = 102;
-
- // other icons
- SKINICON_OTHER_MIRANDA = 200;
- SKINICON_OTHER_EXIT = 201;
- SKINICON_OTHER_SHOWHIDE = 202;
- SKINICON_OTHER_GROUPOPEN = 203; // v0.1.1.0+
- SKINICON_OTHER_GROUPSHUT = 205; // v0.1.1.0+
- SKINICON_OTHER_USERONLINE = 204; // v0.1.0.1+
-
- // menu icons are owned by the module that uses them so are not and should not
- // be skinnable. Except exit and show/hide
-
- // status mode icons. NOTE: These are deprecated in favour of LoadSkinnedProtoIcon()
- SKINICON_STATUS_OFFLINE = 0;
- SKINICON_STATUS_ONLINE = 1;
- SKINICON_STATUS_AWAY = 2;
- SKINICON_STATUS_NA = 3;
- SKINICON_STATUS_OCCUPIED = 4;
- SKINICON_STATUS_DND = 5;
- SKINICON_STATUS_FREE4CHAT = 6;
- SKINICON_STATUS_INVISIBLE = 7;
- SKINICON_STATUS_ONTHEPHONE = 8;
- SKINICON_STATUS_OUTTOLUNCH = 9;
-
-type
-
- PSKINSOUNDDESC = ^TSKINSOUNDDESC;
- TSKINSOUNDDESC = record
- cbSize: int;
- { name to refer to sound when playing and in DB }
- pszName: PChar;
- { description to use for it in options dialog }
- pszDescription: PChar;
- { the default sound file to use, WITHOUT path }
- pszDefaultFile: PChar;
- end;
-
-const
-
- {
- wParam : ICON_ID
- lParam : 0
- Affect : Load an icon from the user's custom skin lib, or from the exe
- if there isn't one loaded, see notes
- Return : HICON for the new icon, do *not* DestroyIcon() the return value
- returns NULL(0) if ICON_ID is invalid, but always success for a valid
- ID.
- }
- MS_SKIN_LOADICON = 'Skin/Icons/Load';
-
- {
- wParam : null terminated string containing the protocol name
- lParam : status_wanted
- Affect : Load an icon representing the status_wanted for a particular protocol, see notes
- Returns: an HICON for the new icon, do NOT DestroyIcon() the return value
- returns NULL(0) on failure.
- Notes : If wParam is NULL(0) the service will load the user's selected
- 'all protocols' status icon
- }
- MS_SKIN_LOADPROTOICON = 'Skin/Icons/LoadProto';
-
- {
- wParam : 0
- lParam : Pointer to a initialised SKINSOUNDDESC
- Affect : Add a new sound so it has a default and can be changed in the options dialog
- Returns: 0 on success, [non zero] on failure
- }
- MS_SKIN_ADDNEWSOUND = 'Skin/Sounds/AddNew';
-
- {
- wParam : 0
- lParam : Pointer to a null terminated string containing the name of the sound to play
- Affect : play a named sound event, play name should of been added
- with MS_SKIN_ADDNEWSOUND, see notes
- Notes : function will not fail, it will play the Windows
- }
- MS_SKIN_PLAYSOUND = 'Skin/Sounds/Play';
-
- {
- wParam : 0
- lParam : 0
- Affect : Sent when the icons DLL has been changed in the options dialog
- and everyone should remake their image lists.
- }
- ME_SKIN_ICONSCHANGED = 'Skin/IconsChanged';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_system.inc b/plugins/ShlExt/inc/m_system.inc deleted file mode 100644 index 90d7f53858..0000000000 --- a/plugins/ShlExt/inc/m_system.inc +++ /dev/null @@ -1,170 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-{$IFNDEF M_SYSTEM}
-{$DEFINE M_SYSTEM}
-
-type
-
- TMM_INTERFACE = record
- cbSize: int;
- _malloc: function(cbSize: Integer): Pointer; cdecl;
- _realloc: function (pb: Pointer; cbSize: Integer): Pointer; cdecl;
- _free: procedure(pb: Pointer); cdecl;
- end;
-
-const
-
- MIRANDANAME = 'Miranda';
-
- {
- wParam : 0
- lParam : 0
- affect : called after all modules have been successfully initialised
- used to resolve double-dependencies in the module load order, see notes
- return : 0
- notes : Can be used to call services, etc that have not yet loaded
- when your module has.
- }
- ME_SYSTEM_MODULESLOADED = 'Miranda/System/ModulesLoaded';
-
- {
- wParam : 0
- lParam : 0
- affect : called just before Miranda terminates, the database is still running
- during this hook
- return : 0
- }
- ME_SYSTEM_SHUTDOWN = 'Miranda/System/Shutdown';
-
- {
- wParam : 0
- lParam : 0
- affect : called before Miranda actually shuts down -- everyone has to agree
- or it is not shut down.
- return : non zero to stop the shutdown
- }
- ME_SYSTEM_OKTOEXIT = 'Miranda/System/OkToExitEvent';
-
- {
- wParam : 0
- lParam : 0
- affect : service which sends everyone the ME_SYSTEM_OKTOEXIT event
- return : true if everyone is okay to exit, otherwise false
- }
- MS_SYSTEM_OKTOEXIT = 'Miranda/System/OkToExit';
-
- {
- wParam : 0
- lParam : 0
- return : returns the version number -- each byte set with version index,
- e.g. 1.2.3.4 $01020304
- }
- MS_SYSTEM_GETVERSION = 'Miranda/System/GetVersion';
-
- {
- wParam : size in bytes of the buffer to be filled
- lParam : pointer to the buffer to be filled
- affect : returns Miranda's version as text with build type such as '1.2.3.4 alpha'
- return : 0 on success -- non zero on failure
- }
- MS_SYSTEM_GETVERSIONTEXT = 'Miranda/System/GetVersionText';
-
- {
- wParam : Handle of a wait object to be used
- lParam : pointer to service name
- affect : causes the service name to be called whenever the wait object
- is signalled with CallService(Service, wParam=hWaitObjeect, lParam=0)
- return : 0 on success, non zero on failure, will always fail if
- more than 64 event objects are already being waited on because
- of the limit imposed by Windows.
- version: implemented after v0.1.2.0+
- other : QueueUserAPC() can be used instead of this service to wait
- for notifications, BUT *only* after v0.1.2.2+ since that deals
- with APC's
- }
- MS_SYSTEM_WAITONHANDLE = 'Miranda/System/WaitOnHandle';
-
- {
- wParam : hWaitObject to be removed
- lParam : 0
- affect : removes the wait object from the list, see above.
- returns: 0 on success, nonzero on failure
- version: implemented after v0.1.2.0+
- }
- MS_SYSTEM_REMOVEWAIT = 'Miranda/System/RemoveWait';
-
- {
- wParam : 0
- lParam : Pointer to an initialised TMM_INTERFACE
- affect : Get function pointers to, malloc(), free() and realloc() used by Miranda
- note : this should only be used carefully, make sure .cbSize is initialised with sizeof(TMM_INTERFACE)
- version: 0.1.2.2+
- }
- MS_SYSTEM_GET_MMI = 'Miranda/System/GetMMI';
-
- {
- wParam=0
- lParam=0
-
- Add a thread to the unwind wait stack that Miranda will poll on
- when it is tearing down modules.
-
- This must be called in the context of the thread that is to be pushed
- i.e. there are no args, it works out what thread is being called
- and gets itself a handle to the calling thread.
- }
- MS_SYSTEM_THREAD_PUSH = 'Miranda/Thread/Push';
-
- {
- wParam=0
- lParam=0
-
- Remove a thread from the unwind wait stack -- it is expected
- that the call be made in the context of the thread to be removed.
-
- Miranda will begin to tear down modules and plugins if/when the
- last thread from the unwind stack is removed.
- }
- MS_SYSTEM_THREAD_POP = 'Miranda/Thread/Pop';
-
- {
- wParam=0
- lParam=0
-
- This hook is fired just before the thread unwind stack is used,
- it allows MT plugins to shutdown threads if they have any special
- processing to do, etc.
- }
- ME_SYSTEM_PRESHUTDOWN = 'Miranda/System/PShutdown';
-
- {
- wParam=0
- lParam=0
-
- Returns TRUE when Miranda has got WM_QUIT and is in the process
- of shutting down
- }
- MS_SYSTEM_TERMINATED = 'Miranda/SysTerm';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_url.inc b/plugins/ShlExt/inc/m_url.inc deleted file mode 100644 index a541576329..0000000000 --- a/plugins/ShlExt/inc/m_url.inc +++ /dev/null @@ -1,39 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_URL}
-{$DEFINE M_URL}
-
-const
-
- {
- wParam : HCONTACT
- lParam : 0
- Affects: bring up the send URL dialogbox for a user
- Returns: 0 on success, nonzero on failure, see notes
- Notes : service returns before the URL is sent.
- }
- MS_URL_SENDURL = 'SRUrl/SendCommand';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_userinfo.inc b/plugins/ShlExt/inc/m_userinfo.inc deleted file mode 100644 index 8f5e1eb654..0000000000 --- a/plugins/ShlExt/inc/m_userinfo.inc +++ /dev/null @@ -1,84 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_USERINFO}
-{$DEFINE M_USERINFO}
-
-const
-
- {
- wParam : HCONTACT
- lParam : 0
- Affects: Show the user details dialog box for a contact, see notes
- Notes : I think this can be used to display "My User Details"... if NULL(0) is used
- }
- MS_USERINFO_SHOWDIALOG = 'UserInfo/ShowDialog';
-
- {
- wParam : 0
- lParam : HCONTACT
- Affects: The details dialog box was opened for a contact maybe NULL(0)
- showing the user details -- see notes
- Notes : The module should do whatever initialisation they need and
- call MS_USERINFO_ADDPAGE one or more times if they want
- pages displayed in the options dialog -- wParam should be passed
- straight as the wParam of MS_USERINFO_ADDPAGE.
- -
- The builtin userinfo module is not loaded til after all plugins
- have loaded -- therefore a HookEvent() for this event will fail,
- use ME_SYSTEM_MODULESLOADED event to know when everything has
- loaded and it's okay to hook this event.
- Version: v0.1.2.0+
- }
- ME_USERINFO_INITIALISE = 'UserInfo/Initialise';
-
- {
- wParam : wParam from ME_USERINFO_INITIALISE
- lParam : pointer to an initialised OPTIONSDIALOGPAGE (see m_options.inc)
- Affects: Adds a page to the details dialog, see notes
- Notes : this service should only be called within the ME_USERINFO_INITIALISE
- event -- when the pages get (WM_INITDIALOG lParam=HCONTACT) strings
- in the passed dialog structure can be freed soon as the service returns
- icons must be kept around (not a problem if you're loading from resource).
- -
- The group elements within the OPTIONSDIALOGPAGE are ignored,
- details dialog page should be 222x132 DLU's -- the details dialog
- box currently has no cancel button, pages will be sent PSN_INFOCHANGED
- thru WM_NOTIFY (idFrom=0) when a protocol ACK is broadcast for
- the correct contact with the type ACKTYPE_GETINFO.
- -
- PSN_INFOCHANGED will also be sent just after the page is created
- to help you out.
- -
- All PSN_* WM_NOTIFY messages have PSHNOTIFY.lParam=(LPARAM)hContact
- Version: v0.1.2.0+
- }
-
- PSN_INFOCHANGED = 1;
- { force-send a PSN_INFOCHANGED to all pages }
- PSM_FORCECHANGED = ($0400 + 100);
-
- MS_USERINFO_ADDPAGE = 'UserInfo/AddPage';
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/m_utils.inc b/plugins/ShlExt/inc/m_utils.inc deleted file mode 100644 index 325b61db24..0000000000 --- a/plugins/ShlExt/inc/m_utils.inc +++ /dev/null @@ -1,279 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF M_UTILS}
-{$DEFINE M_UTILS}
-
-const
-
- RD_ANCHORX_CUSTOM = 0; // function did everything required to the x axis, do no more processing
- RD_ANCHORX_LEFT = 0; // move the control to keep it constant distance from the left edge of the dialog
- RD_ANCHORX_RIGHT = 1; // move the control to keep it constant distance from the right edge of the dialog
- RD_ANCHORX_WIDTH = 2; // size the control to keep it constant distance from both edges of the dialog
- RD_ANCHORX_CENTRE = 4; // move the control to keep it constant distance from the centre of the dialog
- RD_ANCHORY_CUSTOM = 0;
- RD_ANCHORY_TOP = 0;
- RD_ANCHORY_BOTTOM = 8;
- RD_ANCHORY_HEIGHT = 16;
- RD_ANCHORY_CENTRE = 32;
-
- // for MS_UTILS_RESTOREWINDOWPOSITION
-
- RWPF_NOSIZE = 1; // don't use stored size info: leave dialog same size
- RWPF_NOMOVE = 2; // don't use stored position
-
- // for WNDCLASS_COLOURPICKER
-
- CPM_SETCOLOUR = $1000;// lParam=new colour
- CPM_GETCOLOUR = $1001;// returns colour
- CPM_SETDEFAULTCOLOUR = $1002;// lParam=default, used as first custom colour
- CPM_GETDEFAULTCOLOUR = $1003;// returns colour
- CPN_COLOURCHANGED = 1; // sent through WM_COMMAND
-
-type
-
- PUTILRESIZECONTROL = ^TUTILRESIZECONTROL;
- TUTILRESIZECONTROL = record
- cbSize: int;
- wId: int; // control ID
- rcItem: TRect; // original control rectangle, relative to dialog
- // modify in-placee to specify the new position
- dlgOriginalSize: TSize; // size of dialog client area in template
- dlgNewSize: TSize; // current size of dialog client area
- end;
-
- TDIALOGRESIZERPROC = function(hwndDlg: THandle; lParam: LPARAM; urc: PUTILRESIZECONTROL): int; cdecl;
-
- PUTILRESIZEDIALOG = ^TUTILRESIZEDIALOG;
- TUTILRESIZEDIALOG = record
- cbSize: int;
- hwndDlg: THandle;
- hInstance: THandle;
- lpTemplate: PChar;
- lParam: LPARAM;
- pfnResizer: TDIALOGRESIZERPROC;
- end;
-
- PCountryListEntry = ^TCountryListEntry;
- TCountryListEntry = record
- id: int;
- szName: PChar;
- end;
-
- PWINDOWLISTENTRY = ^TWINDOWLISTENTRY;
- TWINDOWLISTENTRY = record
- hList: THandle;
- hWnd: THandle;
- hContact: THandle;
- end;
-
- PSAVEWINDOWPOS = ^TSAVEWINDOWPOS;
- TSAVEWINDOWPOS = record
- hWnd: THandle;
- hContact: THandle;
- szModule: PChar; // module name eto store the settings in
- szNamePrefix: PChar; // text to prefix on 'x', 'width', etc
- end;
-
-const
-
- {
- wParam : bOpenInNewWindow
- lParam : Pointer to a null terminated string containing Url
- Affect : Open a URRL in the user's default web browser, see notes
- Returns: 0 on success, [non zero on failure]
- Notes : bOpenInWindow should be zero to open the URL in the browoser window
- the user last used, or nonzero to open in a new browser window,
- if there's no browser running, it will be started to show the URL
- Version: v0.1.0.1+
- }
- MS_UTILS_OPENURL = 'Utils/OpenURL';
-
- {
- wParam : 0
- lParam : Pointer to an initalised TUTILRESIZEDIALOG structure
- Affect : Resize a dialog by calling a custom routine to move each control, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : Does not support DIALOGTEMPLATEEX dialogboxes, and will return
- failure if you try to resize one.-
- the dialog iteself should have been resized prior to calling this
- service, .pfnResizer is called once for each control in the dialog
- .pfnResizer should return a combination of one RD_ANCHORx_ and one RD_ANCHORy constant
- Version: v0.1.0.1+
- }
- MS_UTILS_RESIZEDIALOG = 'Utils/ResizeDialog';
-
- {
- wParam : countryID
- lParam : 0
- Affect : Get the name of a country given it's number, e.g. 44 = UK
- Returns: Returns a pointer to a string containing the country name on success
- NULL(0) on failure
- Version: v0.1.2.0+
- }
- MS_UTILS_GETCOUNTRYBYNUMBER = 'Utils/GetCountryByNumber';
-
- {
- wParam : Pointer to an int to be filled with count -- !TODO! test.
- lParam : Pointer to an PCountryListEntry, see notes
- Affect : Get the full list of country IDs, see notes
- Returns: 0 always
- Notes : the list is sorted alphabetically by name, on the assumption
- it's quicker to search numbers that are out of outer, than strings
- that are out of order. a NULL(0) entry terminates
- -
- Neither wParam or lParam can be NULL(0)
- -
- lParam is filled with the first entry, it can be accessed as a pointer,
- to get the next entry, increment the pointer by sizeof(Pointer) NOT
- sizeof(TCountryList), only increment the pointer as many times as
- given by iCount.
- -
- this data can NOT be copied if an array of TCountryListEntry's is passed
- so don't try it.
- Version: v0.1.2.0+
- }
- MS_UTILS_GETCOUNTRYLIST = 'Utils/GetCountryList';
-
- // see WindowList_* functions below
-
- {
- wParam : 0
- lParam : 0
- Affect : Allocate a window list
- Returns: A handle to the new window list
- Version: v0.1.0.1+
- }
- MS_UTILS_ALLOCWINDOWLIST = 'Utils/AllocWindowList';
-
- {
- wParam : 0
- lParam : Pointer to an initalised TWINDOWLISTENTRY structure
- Affect : Add a window to a given window list handle
- Returns: 0 on success, [non zero] on failure
- Version: v0.1.0.1+
- }
- MS_UTILS_ADDTOWINDOWLIST = 'Utils/AddToWindowList';
-
- {
- wParam : Handle to window list to remove from
- lParam : Window handle to remove
- Affect : Remove a window from the specified window list
- Returns: 0 on success, [non zero] on failure
- Version: v0.1.0.1+
- }
- MS_UTILS_REMOVEFROMWINDOWLIST = 'Utils/RemoveFromWindowList';
-
- {
- wParam : Handle to the window list to look in
- lParam : Handle to a HCONTACT to find in the window list
- Affect : Find a window handle given the hContact
- Returns: The found window handle or NULL(0) on failure
- Version: v0.1.0.1+
- }
- MS_UTILS_FINDWINDOWINLIST = 'Utils/FindWindowInList';
-
- {
- wParam : Handle to window list
- lParam : Pointer to TMSG (initalised with what to broadcast)
- Affect : Broadcast a message to all windows in a list, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : only TMSG.Message, .wParam, .lParam are used
- Version: v0.1.0.1+
- }
- MS_UTILS_BROADCASTTOWINDOWLIST = 'Utils/BroadcastToWindowList';
-
- {
- There aren't any services here, there's no need for them, the control class
- will obey the SS_LEFT (0), SS_CENTER (1), SS_RIGHT(2) styles
- the control will send STN_CLICKED via WM_COMMAND when the link itself is clicked
- -
- These are defined by STATIC controls and STN_CLICKED is sent to standard
- STATIC classes when they're clicked -- look at WINAPI docs for more info
- }
- WNDCLASS_HYPERLINK = 'Hyperlink';
-
- {
- wParam : 0
- lParam : Pointer to a initialised TSAVEWINDOWPOS structure
- Affect :
- Returns: 0 on success, [non zero] on failure
- Notes :
- Version: v0.1.1.0+
- }
- MS_UTILS_SAVEWINDOWPOSITION = 'Utils/SaveWindowPos';
-
- {
- wParam : see RWPF_* flags
- lParam : Pointer to a initalised TSAVEWINDOWPOS
- Affect : Restores the position of a window from the database, see notes
- Returns: 0 on success, [non zero] on failure
- Notes : If no position info was found, the service will return 1.
- The NoSize version won't use stored information size, the window
- is left the same size
- -
- See Utils_RestoreWindowPosition() Helper function, this function is
- a bit different from the C function (which can be inlined too! dammit)
- that there's only one function and not three (which just passed different flags)
- Version: v0.1.1.0+
- }
- MS_UTILS_RESTOREWINDOWPOSITION = 'Utils/RestoreWindowPos';
-
- {
- Colour picker control, see CPM_* and CPN_* constants above
- }
- WNDCLASS_COLOURPICKER = 'ColourPicker';
-
- {
- wParam : 0
- lParam : Pointer to a null terminated string containing filename
- Affect : Loads a bitmap (or other graphic type, see Notes
- Returns: HBITMAP on success, NULL(0) on failure
- Notes : This function also supports JPEG, GIF (and maybe PNG too)
- For speed, if the file extention is .bmp or .rle it will use LoadImage()
- and not load OLE for the extra image support
- -
- Remember to delete the returned handle with DeleteObject (see GDI documentation for WINAPI)
- Version: v0.1.2.1+
- }
- MS_UTILS_LOADBITMAP = 'Utils/LoadBitmap';
-
- {
- wParam : byte length of buffer (not to be confused with byte range)
- lParam : Pointer to buffer
- Affect : Get the filter strings for use in the open file dialog, see notes
- Returns: 0 on success [non zero] on failure
- Notes : See the WINAPI under OPENFILENAME.lpStrFiler for formatting,
- an 'All bitmaps' item is alway first, and 'All files' is always last
- -
- The returned string is always formatted
- -
- To build this filter, the filter string consists of
- filter followed by a descriptive text
- followed by more filters and their descriptive texts -- end with double NULL(0)
- e.g. *.bmp' #0 'All bitmaps' #0 '*.*' #0 'All Files' #0 #0
- }
- MS_UTILS_GETBITMAPFILTERSTRINGS = 'Utils/GetBitmapFilterStrings';
-
-{$endif}
diff --git a/plugins/ShlExt/inc/m_v8.inc b/plugins/ShlExt/inc/m_v8.inc deleted file mode 100644 index e0c9d1e0c8..0000000000 --- a/plugins/ShlExt/inc/m_v8.inc +++ /dev/null @@ -1,62 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-{$IFNDEF V8}
-{$DEFINE V8}
-
-type
-
- PMUUID = ^TMUUID;
- TMUUID = record
- a: LongWord;
- b, c: Word;
- d: array[0..7] of Byte;
- end;
-
- PPLUGININFOEX = ^TPLUGININFOEX;
- TPLUGININFOEX = record
- cbSize: int;
- shortName: PChar;
- version: DWORD;
- description: PChar;
- author: PChar;
- authorEmail: PChar;
- copyright: PChar;
- homepage: PChar;
- isTransient: Byte; // leave zero for now
- { one of the DEFMOD_* consts in m_plugin or zero, if non zero, this will
- suppress loading of the specified builtin module }
- replacesDefaultModule: int;
- uuid: TMUUID;
- end;
-
- { any module must export the below functions to be valid plugin
- the export names MUST be 'MirandaPluginInfo' 'Load' 'Unload' }
-
- // defined in newpluginapi.inc
-
- //TMirandaPluginInfo = function(mirandaVersion: DWORD): PPLUGININFO; cdecl;
- //TLoad = function(link: PPLUGINLINK): int; cdecl;
- //TUnload = function: int; cdecl;
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/newpluginapi.inc b/plugins/ShlExt/inc/newpluginapi.inc deleted file mode 100644 index 85a7df9a2b..0000000000 --- a/plugins/ShlExt/inc/newpluginapi.inc +++ /dev/null @@ -1,94 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-{$IFNDEF NEWPLUGINAPI}
-{$DEFINE NEWPLUGINAPI}
-
-const
-
- MAXMODULELABELLENGTH = 64;
-
-type
-
- PPLUGININFO = ^TPLUGININFO;
- TPLUGININFO = record
- cbSize: int;
- shortName: PChar;
- version: DWORD;
- description: PChar;
- author: PChar;
- authorEmail: PChar;
- copyright: PChar;
- homepage: PChar;
- isTransient: Byte; // leave zero for now
- { one of the DEFMOD_* consts in m_plugin or zero, if non zero, this will
- suppress loading of the specified builtin module }
- replacesDefaultModule: int;
- end;
-
- { modules.h is never defined -- no check needed }
-
- TMIRANDAHOOK = function(wParam: WPARAM; lParam: LPARAM): int; cdecl;
- TMIRANDASERVICE = function(wParam: WPARAM; lParam: LPARAM): int; cdecl;
-
- //see modules.h tor what all this stuff is
-
- TCreateHookableEvent = function(const char: PChar): THandle; cdecl;
- TDestroyHookableEvent = function(Handle: THandle): int; cdecl;
- TNotifyEventHooks = function(Handle: THandle; wParam: WPARAM; lParam: LPARAM): int; cdecl;
- THookEvent = function(const char: PChar; MIRANDAHOOK: TMIRANDAHOOK): THandle; cdecl;
- THookEventMessage = function(const char: PChar; Wnd: THandle; wMsg: Integer): THandle; cdecl;
- TUnhookEvent = function(Handle: THandle): int; cdecl;
- TCreateServiceFunction = function(const char: PChar; MIRANDASERVICE: TMIRANDASERVICE): THandle; cdecl;
- TCreateTransientServiceFunction = function(const char: PChar; MIRANDASERVICE: TMIRANDASERVICE): THandle; cdecl;
- TDestroyServiceFunction = function(Handle: THandle): int; cdecl;
- TCallService = function(const char: PChar; wParam: WPARAM; lParam: LPARAM): int; cdecl;
- TServiceExists = function(const char: PChar): int; cdecl;
-
- PPLUGINLINK = ^TPLUGINLINK;
- TPLUGINLINK = record
- CreateHookableEvent: TCreateHookableEvent;
- DestroyHookableEvent: TDestroyHookableEvent;
- NotifyEventHooks: TNotifyEventHooks;
- HookEvent: THookEvent;
- HookEventMessage: THookEventMessage;
- UnhookEvent: TUnhookEvent;
- CreateServiceFunction: TCreateServiceFunction;
- CreateTransientServiceFunction: TCreateTransientServiceFunction;
- DestroyServiceFunction: TDestroyServiceFunction;
- CallService: TCallService;
- ServiceExists: TServiceExists; // v0.1.0.1+
- end;
-
- { any module must export the below functions to be valid plugin
- the export names MUST be 'MirandaPluginInfo' 'Load' 'Unload' }
-
- TMirandaPluginInfo = function(mirandaVersion: DWORD): PPLUGININFO; cdecl;
- TLoad = function(link: PPLUGINLINK): int; cdecl;
- TUnload = function: int; cdecl;
-
-const
-
- CALLSERVICE_NOTFOUND = $80000000;
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/statusmodes.inc b/plugins/ShlExt/inc/statusmodes.inc deleted file mode 100644 index 2cf180569f..0000000000 --- a/plugins/ShlExt/inc/statusmodes.inc +++ /dev/null @@ -1,54 +0,0 @@ -(*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2004 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*)
-
-{$IFNDEF STATUSMODES}
-{$DEFINE STATUSMODES}
-
-const
-
- // add 1 to the ID_STATUS_CONNECTING to mark retries (v0.1.0.1+)
- // e.g. ID_STATUS_CONNECTING+2 is the third connection attempt, or the second retry
-
- ID_STATUS_CONNECTING = 1;
-
- // max retries is just a marker, so that the clist knows what
- // numbers represent retries, it should set any kind of limit on the number
- // of retries you can and/or should do
-
- MAX_CONNECT_RETRIES = 10000;
-
- // and the modes!
-
- ID_STATUS_OFFLINE = 40071;
- ID_STATUS_ONLINE = 40072;
- ID_STATUS_AWAY = 40073;
- ID_STATUS_DND = 40074;
- ID_STATUS_NA = 40075;
- ID_STATUS_OCCUPIED = 40076;
- ID_STATUS_FREECHAT = 40077;
- ID_STATUS_INVISIBLE = 40078;
- ID_STATUS_ONTHEPHONE = 40079;
- ID_STATUS_OUTTOLUNCH = 40080;
-
-{$ENDIF}
diff --git a/plugins/ShlExt/inc/testdll.dpr b/plugins/ShlExt/inc/testdll.dpr deleted file mode 100644 index 478212d82c..0000000000 --- a/plugins/ShlExt/inc/testdll.dpr +++ /dev/null @@ -1,60 +0,0 @@ -library testdll;
-
-uses
-
- m_globaldefs, m_api, Windows;
-
- {$include m_helpers.inc}
-
- function MirandaPluginInfo(mirandaVersion: DWORD): PPLUGININFO; cdecl;
- begin
- Result := @PLUGININFO;
- PLUGININFO.cbSize := sizeof(TPLUGININFO);
- PLUGININFO.shortName := 'Plugin Template';
- PLUGININFO.version := PLUGIN_MAKE_VERSION(0,0,0,1);
- PLUGININFO.description := 'The long description of your plugin, to go in the plugin options dialog';
- PLUGININFO.author := 'J. Random Hacker';
- PLUGININFO.authorEmail := 'noreply@sourceforge.net';
- PLUGININFO.copyright := '(c) 2003 J. Random Hacker';
- PLUGININFO.homepage := 'http://miranda-icq.sourceforge.net/';
- PLUGININFO.isTransient := 0;
- PLUGININFO.replacesDefaultModule := 0;
- end;
-
- function PluginMenuCommand(wParam: WPARAM; lParam: LPARAM): Integer; cdecl;
- begin
- Result := 0;
- // this is called by Miranda, thus has to use the cdecl calling convention
- // all services and hooks need this.
- MessageBox(0, 'Just groovy, baby!', 'Plugin-o-rama', MB_OK);
- end;
-
- function Load(link: PPLUGINLINK): int; cdecl;
- var
- mi: TCListMenuItem;
- begin
- // this line is VERY VERY important, if it's not present, expect crashes.
- PLUGINLINK := Pointer(link);
- pluginLink^.CreateServiceFunction('TestPlug/MenuCommand', @PluginMenuCommand);
- FillChar(mi, sizeof(mi), 0);
- mi.cbSize := sizeof(mi);
- mi.position := $7FFFFFFF;
- mi.flags := 0;
- mi.hIcon := LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
- mi.pszName := '&Test Plugin...';
- mi.pszService := 'TestPlug/MenuCommand';
- pluginLink^.CallService(MS_CLIST_ADDMAINMENUITEM, 0, lParam(@mi));
- Result := 0;
- end;
-
- function Unload: int; cdecl;
- begin
- Result := 0;
- end;
-
- exports
-
- MirandaPluginInfo, Load, Unload;
-
-begin
-end.
diff --git a/plugins/ShlExt/shlc.inc b/plugins/ShlExt/shlc.inc index 122e0fee14..e1b76607f4 100644 --- a/plugins/ShlExt/shlc.inc +++ b/plugins/ShlExt/shlc.inc @@ -1,168 +1,151 @@ {$IFDEF SHL_IDC} -const - IDD_SHLOPTS = 101; - IDC_USEGROUPS = 1014; - IDC_CLISTGROUPS = 1015; -// Show "HIT" - IDC_SHOWFULL = 1016; - IDC_NOPROF = 1020; - IDC_SHOWINVISIBLES = 1021; - IDC_HIDEOFFLINE = 1022; -// only in the options dialog - IDC_STATUS = 1023; - IDC_CAPMENUS = 1025; - IDC_CAPSTATUS = 1026; - IDC_CAPSHLSTATUS = 1027; - IDC_REMOVE = 1028; - IDC_USEOWNERDRAW = 1029; -{$ENDIF} -{$IFDEF SHL_KEYS} -const - SHLExt_Name: PChar = 'shlext15';
- SHLExt_MRU: PChar = 'MRU'; - SHLExt_UseGroups: PChar = 'UseGroups'; - SHLExt_UseCListSetting:PChar = 'UseCLGroups'; - SHLExt_UseHITContacts:PChar = 'UseHITContacts'; -// HIT2 contacts will get your messages but don't know your state - SHLExt_UseHIT2Contacts: PChar = 'UseHIT2Contacts'; - SHLExt_ShowNoProfile:PChar = 'ShowNoProfile'; - SHLExt_ShowNoIcons:PChar = 'ShowNoIcons'; - SHLExt_ShowNoOffline:PChar = 'ShowNoOffline'; -{$ENDIF} -{$IFDEF SHLCOM} -const - - S_OK = 0; - S_FALSE = 1; - - E_UNEXPECTED = $8000FFFF; - E_NOTIMPL = $80004001; - E_INVALIDARG = $80070057; - - CLASS_E_NOAGGREGATION = $80040110; - CLASS_E_CLASSNOTAVAILABLE = $80040111; - - CLSCTX_INPROC_SERVER = $1; - - { for FORMATETC } - - TYMED_HGLOBAL = 1; - DVASPECT_CONTENT = 1; - -type - - PGUID = ^TGUID; - TGUID = record - D1: Longint; - D2: Word; - D3: Word; - D4: array[0..7] of Byte; - end; - - TIID = TGUID; - TCLSID = TGUID; - - TStgMedium = record - tymed: Longint; - case Integer of - 0: (hBitmap: HBitmap; unkForRelease: Pointer{IUnknown}); - 1: (hMetaFilePict: THandle); - 2: (hEnhMetaFile: THandle); - 3: (hGlobal: HGlobal); - 4: (lpszFileName: Pointer{POleStr}); - 5: (stm: Pointer{IUnknown}); - 6: (stg: Pointer{IStorage}); - end; - - PFormatEtc = ^TFormatEtc; - TFormatEtc = record - cfFormat: Word; {TClipFormat;} - ptd: Pointer; {PDVTargetDevice;} - dwAspect: Longint; - lindex: Longint; - tymed: Longint; - end; - -{$ENDIF} -{$IFDEF COM_STRUCTS} -const - - IID_IUnknown : TGUID = ( - D1:$00000000; - D2:$0000; - D3:$0000; - D4:($C0,$00,$00,$00,$00,$00,$00,$46) - ); - - IID_IClassFactory : TGUID = ( - D1:$00000001; - D2:$0000; - D3:$0000; - D4:($C0,$00,$00,$00,$00,$00,$00,$46) - ); - - IID_IShellExtInit : TGUID = ( - D1:$000214E8; - D2:$0000; - D3:$0000; - D4:($C0,$00,$00,$00,$00,$00,$00,$46) - ); - - IID_IContextMenu : TGUID = ( - D1:$000214E4; - D2:$0000; - D3:$0000; - D4:($C0,$00,$00,$00,$00,$00,$00,$46) - ); - - IID_IContextMenu2 : TGUID = ( - D1:$000214F4; - D2:$0000; - D3:$0000; - D4:($C0,$00,$00,$00,$00,$00,$00,$46) - ); - - IID_IContextMenu3 : TGUID = ( - D1:$BCFCE0A0; - D2:$EC17; - D3:$11D0; - D4:($8D,$10,$00,$A0,$C9,$0F,$27,$19) - ); - - IID_WICImagingFactory: TGUID = ( - D1:$EC5EC8A9; - D2:$C395; - D3:$4314; - D4:($9C,$77,$54,$D7,$A9,$35,$FF,$70) - ); - - - // Vista+ only - - CLSID_WICImagingFactory : TGUID = ( - D1:$cacaf262; - D2:$9370; - D3:$4615; - D4:($A1,$3B,$9F,$55,$39,$DA,$4C,$0A) - ); - - // anything before 0.0.1.5 was : {A321A032-7976-11d6-A310-ED893982BF28} - // changed to a new GUID to avoid older plugins - // {72013A26-A94C-11d6-8540-A5E62932711D} - // the IPC header now checks the plugin version given anyway. - - CLSID_ISHLCOM : TGUID = ( - D1: $72013a26; - D2: $a94c; - D3: $11d6; - D4: ($85,$40,$a5,$e6,$29,$32,$71,$1d); - ); -{$ENDIF} -{$IFDEF COMAPI} - function CoCreateInstance(const rclsid: TCLSID; pUnkOuter: Pointer; dwClsContext: DWORD; const riid: TIID; var ppv): HResult; stdcall; external 'ole32.dll' name 'CoCreateInstance'; - procedure ReleaseStgMedium(var medium: TStgMedium); stdcall; external 'ole32.dll' name 'ReleaseStgMedium'; - function IsEqualGUID(const guid1, guid2: TGUID): Boolean; stdcall; external 'ole32.dll' name 'IsEqualGUID'; - function IsEqualIID(const iid1, iid2: TIID): Boolean; stdcall; external 'ole32.dll' name 'IsEqualGUID'; - function IsEqualCLSID(const clsid1, clsid2: TCLSID): Boolean; stdcall; external 'ole32.dll' name 'IsEqualGUID'; - function QueueUserAPC(pfnAPC: Pointer; hThread: THandle; dwData: DWORD): BOOL; stdcall; external 'kernel32' name 'QueueUserAPC'; +
+const
+ IDD_SHLOPTS = 101;
+ IDC_USEGROUPS = 1014;
+ IDC_CLISTGROUPS = 1015;
+ // Show "HIT"
+ IDC_SHOWFULL = 1016;
+ IDC_NOPROF = 1020;
+ IDC_SHOWINVISIBLES = 1021;
+ IDC_HIDEOFFLINE = 1022;
+ // only in the options dialog
+ IDC_STATUS = 1023;
+ IDC_CAPMENUS = 1025;
+ IDC_CAPSTATUS = 1026;
+ IDC_CAPSHLSTATUS = 1027;
+ IDC_REMOVE = 1028;
+ IDC_USEOWNERDRAW = 1029;
+{$ENDIF}
+{$IFDEF SHL_KEYS}
+
+const
+ SHLExt_Name: PChar = 'shlext15';
+ SHLExt_MRU: PChar = 'MRU';
+ SHLExt_UseGroups: PChar = 'UseGroups';
+ SHLExt_UseCListSetting: PChar = 'UseCLGroups';
+ SHLExt_UseHITContacts: PChar = 'UseHITContacts';
+ // HIT2 contacts will get your messages but don't know your state
+ SHLExt_UseHIT2Contacts: PChar = 'UseHIT2Contacts';
+ SHLExt_ShowNoProfile: PChar = 'ShowNoProfile';
+ SHLExt_ShowNoIcons: PChar = 'ShowNoIcons';
+ SHLExt_ShowNoOffline: PChar = 'ShowNoOffline';
+{$ENDIF}
+{$IFDEF SHLCOM}
+
+const
+
+ S_OK = 0;
+ S_FALSE = 1;
+
+ E_UNEXPECTED = $8000FFFF;
+ E_NOTIMPL = $80004001;
+ E_INVALIDARG = $80070057;
+
+ CLASS_E_NOAGGREGATION = $80040110;
+ CLASS_E_CLASSNOTAVAILABLE = $80040111;
+
+ CLSCTX_INPROC_SERVER = $1;
+
+ { for FORMATETC }
+
+ TYMED_HGLOBAL = 1;
+ DVASPECT_CONTENT = 1;
+
+type
+
+ PGUID = ^TGUID;
+
+ TGUID = record
+ D1: Longint;
+ D2: Word;
+ D3: Word;
+ D4: array [0 .. 7] of Byte;
+ end;
+
+ TIID = TGUID;
+ TCLSID = TGUID;
+
+ TStgMedium = record
+ tymed: Longint;
+ case Integer of
+ 0:
+ (hBitmap: hBitmap; unkForRelease: Pointer { IUnknown } );
+ 1:
+ (hMetaFilePict: THandle);
+ 2:
+ (hEnhMetaFile: THandle);
+ 3:
+ (hGlobal: hGlobal);
+ 4:
+ (lpszFileName: Pointer { POleStr } );
+ 5:
+ (stm: Pointer { IUnknown } );
+ 6:
+ (stg: Pointer { IStorage } );
+ end;
+
+ PFormatEtc = ^TFormatEtc;
+
+ TFormatEtc = record
+ cfFormat: Word; { TClipFormat; }
+ ptd: Pointer; { PDVTargetDevice; }
+ dwAspect: Longint;
+ lindex: Longint;
+ tymed: Longint;
+ end;
+
+{$ENDIF}
+{$IFDEF COM_STRUCTS}
+
+const
+
+ IID_IUnknown: TGUID = (D1: $00000000; D2: $0000; D3: $0000;
+ D4: ($C0, $00, $00, $00, $00, $00, $00, $46));
+
+ IID_IClassFactory: TGUID = (D1: $00000001; D2: $0000; D3: $0000;
+ D4: ($C0, $00, $00, $00, $00, $00, $00, $46));
+
+ IID_IShellExtInit: TGUID = (D1: $000214E8; D2: $0000; D3: $0000;
+ D4: ($C0, $00, $00, $00, $00, $00, $00, $46));
+
+ IID_IContextMenu: TGUID = (D1: $000214E4; D2: $0000; D3: $0000;
+ D4: ($C0, $00, $00, $00, $00, $00, $00, $46));
+
+ IID_IContextMenu2: TGUID = (D1: $000214F4; D2: $0000; D3: $0000;
+ D4: ($C0, $00, $00, $00, $00, $00, $00, $46));
+
+ IID_IContextMenu3: TGUID = (D1: $BCFCE0A0; D2: $EC17; D3: $11D0;
+ D4: ($8D, $10, $00, $A0, $C9, $0F, $27, $19));
+
+ IID_WICImagingFactory: TGUID = (D1: $EC5EC8A9; D2: $C395; D3: $4314;
+ D4: ($9C, $77, $54, $D7, $A9, $35, $FF, $70));
+
+
+ // Vista+ only
+
+ CLSID_WICImagingFactory: TGUID = (D1: $CACAF262; D2: $9370; D3: $4615;
+ D4: ($A1, $3B, $9F, $55, $39, $DA, $4C, $0A));
+
+ // anything before 0.0.1.5 was : {A321A032-7976-11d6-A310-ED893982BF28}
+ // changed to a new GUID to avoid older plugins
+ // {72013A26-A94C-11d6-8540-A5E62932711D}
+ // the IPC header now checks the plugin version given anyway.
+
+ CLSID_ISHLCOM: TGUID = (D1: $72013A26; D2: $A94C; D3: $11D6;
+ D4: ($85, $40, $A5, $E6, $29, $32, $71, $1D););
+{$ENDIF}
+{$IFDEF COMAPI}
+function CoCreateInstance(const rclsid: TCLSID; pUnkOuter: Pointer; dwClsContext: DWORD;
+ const riid: TIID; var ppv): HResult; stdcall; external 'ole32.dll' name 'CoCreateInstance';
+procedure ReleaseStgMedium(var medium: TStgMedium); stdcall;
+ external 'ole32.dll' name 'ReleaseStgMedium';
+function IsEqualGUID(const guid1, guid2: TGUID): Boolean; stdcall;
+ external 'ole32.dll' name 'IsEqualGUID';
+function IsEqualIID(const iid1, iid2: TIID): Boolean; stdcall;
+ external 'ole32.dll' name 'IsEqualGUID';
+function IsEqualCLSID(const clsid1, clsid2: TCLSID): Boolean; stdcall;
+ external 'ole32.dll' name 'IsEqualGUID';
+function QueueUserAPC(pfnAPC: Pointer; hThread: THandle; dwData: DWORD): BOOL; stdcall;
+ external 'kernel32' name 'QueueUserAPC';
{$ENDIF} diff --git a/plugins/ShlExt/shlcom.pas b/plugins/ShlExt/shlcom.pas index 79a9134012..d693dcb300 100644 --- a/plugins/ShlExt/shlcom.pas +++ b/plugins/ShlExt/shlcom.pas @@ -1,2383 +1,2512 @@ unit shlcom; - -{$IFDEF FPC} - {$PACKRECORDS 4} - {$MODE Delphi} -{$ENDIF} - -interface - -uses - - Windows, m_globaldefs, shlipc, shlicons; - - {$define COM_STRUCTS} - {$define SHLCOM} - {$include shlc.inc} - {$undef SHLCOM} - {$undef COM_STRUCTS} - - function DllGetClassObject(const CLSID: TCLSID; const IID: TIID; - var Obj): HResult; stdcall; - function DllCanUnloadNow: HResult; stdcall; - - procedure InvokeThreadServer; - - procedure CheckRegisterServer; - - procedure CheckUnregisterServer; - - function RemoveCOMRegistryEntries: HResult; - - function ExtractIcon(hInst: THandle; pszExe: PChar; nIndex: Integer): HICON; stdcall; external 'shell32.dll' name 'ExtractIconA'; - -implementation - -var - - dllpublic: record - FactoryCount: Integer; - ObjectCount: Integer; - end; - - VistaOrLater: Boolean; - - {$include m_database.inc} - {$include m_clist.inc} - {$include m_protocols.inc} - {$include m_protosvc.inc} - {$include m_ignore.inc} - {$include m_skin.inc} - {$include m_file.inc} - {$include m_system.inc} - {$include m_langpack.inc} - {$include m_skin.inc} - {$include statusmodes.inc} - - {$define COMAPI} - {$include shlc.inc} - {$undef COMAPI} - - {$include m_helpers.inc} - -const - - IPC_PACKET_SIZE = $1000 * 32; - //IPC_PACKET_NAME = 'm.mi.miranda.ipc'; // prior to 1.0.6.6 - //IPC_PACKET_NAME = 'mi.miranda.IPCServer'; // prior to 2.0.0.9
- IPC_PACKET_NAME = 'm.mi.miranda.ipc.server'; - -const - -{ Flags returned by IContextMenu*:QueryContextMenu() } - - CMF_NORMAL = $00000000; - CMF_DEFAULTONLY = $00000001; - CMF_VERBSONLY = $00000002; - CMF_EXPLORE = $00000004; - CMF_NOVERBS = $00000008; - CMF_CANRENAME = $00000010; - CMF_NODEFAULT = $00000020; - CMF_INCLUDESTATIC = $00000040; - CMF_RESERVED = $FFFF0000; { view specific } - -{ IContextMenu*:GetCommandString() uType flags } - - GCS_VERBA = $00000000; // canonical verb - GCS_HELPTEXTA = $00000001; // help text (for status bar) - GCS_VALIDATEA = $00000002; // validate command exists - GCS_VERBW = $00000004; // canonical verb (unicode) - GC_HELPTEXTW = $00000005; // help text (unicode version) - GCS_VALIDATEW = $00000006; // validate command exists (unicode) - GCS_UNICODE = $00000004; // for bit testing - Unicode string - GCS_VERB = GCS_VERBA; // - GCS_HELPTEXT = GCS_HELPTEXTA; - GCS_VALIDATE = GCS_VALIDATEA; - -type - - { this structure is returned by InvokeCommand() } - - PCMInvokeCommandInfo = ^TCMInvokeCommandInfo; - TCMInvokeCommandInfo = packed record - cbSize: DWORD; - fMask: DWORD; - hwnd: HWND; - lpVerb: PChar; { maybe index, type cast as Integer } - lpParams: PChar; - lpDir: PChar; - nShow: Integer; - dwHotkey: DWORD; - hIcon: THandle; - end; - -{ completely stolen from modules.c: 'NameHashFunction' modified slightly } - - function StrHash(const szStr: PChar): DWORD; cdecl; - asm - // esi content has to be preserved with basm - push esi - xor edx,edx - xor eax,eax - mov esi,szStr - mov al,[esi] - xor cl,cl - @@lph_top: //only 4 of 9 instructions in here don't use AL, so optimal pipe use is impossible - xor edx,eax - inc esi - xor eax,eax - and cl,31 - mov al,[esi] - add cl,5 - test al,al - rol eax,cl //rol is u-pipe only, but pairable - //rol doesn't touch z-flag - jnz @@lph_top //5 clock tick loop. not bad. - xor eax,edx - pop esi - end; - - function CreateProcessUID(const pid: Cardinal): string; - var - pidrep: string[16]; - begin - str(pid, pidrep); - Result := Concat('mim.shlext.', pidrep, '$'); - end; - - function CreateUID: string; - var - pidrep, tidrep: string[16]; - begin - str(GetCurrentProcessId(), pidrep); - str(GetCurrentThreadId(), tidrep); - Result := Concat('mim.shlext.caller', pidrep, '$', tidrep); - end; - - // FPC doesn't support array[0..n] of Char extended syntax with Str() - - function wsprintf(lpOut, lpFmt: PChar; ArgInt: Integer): Integer; cdecl; external 'user32.dll' name 'wsprintfA'; - - procedure Str(i: Integer; S: PChar); - begin - i := wsprintf(s, '%d', i); - if i > 2 then PChar(s)[i] := #0; - end; - -{ IShlCom } - -type - - PLResult = ^LResult; - - // bare minimum interface of IDataObject, since GetData() is only required. - - PVTable_IDataObject = ^TVTable_IDataObject; - TVTable_IDataObject = record - { IUnknown } - QueryInterface: Pointer; - AddRef: function(Self: Pointer): Cardinal; stdcall; - Release: function(Self: Pointer): Cardinal; stdcall; - { IDataObject } - GetData: function(Self: Pointer; var formatetcIn: TFormatEtc; var medium: TStgMedium): HResult; stdcall; - GetDataHere: Pointer; - QueryGetData: Pointer; - GetCanonicalFormatEtc: Pointer; - SetData: Pointer; - EnumFormatEtc: Pointer; - DAdvise: Pointer; - DUnadvise: Pointer; - EnumDAdvise: Pointer; - end; - - PDataObject_Interface = ^TDataObject_Interface; - TDataObject_Interface = record - ptrVTable: PVTable_IDataObject; - end; - - { TShlComRec inherits from different interfaces with different function tables - all "compiler magic" is lost in this case, but it's pretty easy to return - a different function table for each interface, IContextMenu is returned - as IContextMenu'3' since it inherits from '2' and '1' } - - PVTable_IShellExtInit = ^TVTable_IShellExtInit; - TVTable_IShellExtInit = record - { IUnknown } - QueryInterface: Pointer; - AddRef: Pointer; - Release: Pointer; - { IShellExtInit } - Initialise: Pointer; - end; - - PShlComRec = ^TShlComRec; - PShellExtInit_Interface = ^TShellExtInit_Interface; - TShellExtInit_Interface = record - { pointer to function table } - ptrVTable: PVTable_IShellExtInit; - { instance data } - ptrInstance: PShlComRec; - { function table itself } - vTable: TVTable_IShellExtInit; - end; - - PVTable_IContextMenu3 = ^TVTable_IContextMenu3; - TVTable_IContextMenu3 = record - { IUnknown } - QueryInterface: Pointer; - AddRef: Pointer; - Release: Pointer; - { IContextMenu } - QueryContextMenu: Pointer; - InvokeCommand: Pointer; - GetCommandString: Pointer; - { IContextMenu2 } - HandleMenuMsg: Pointer; - { IContextMenu3 } - HandleMenuMsg2: Pointer; - end; - - PContextMenu3_Interface = ^TContextMenu3_Interface; - TContextMenu3_Interface = record - ptrVTable: PVTable_IContextMenu3; - ptrInstance: PShlComRec; - vTable: TVTable_IContextMenu3; - end; - - PCommon_Interface = ^TCommon_Interface; - TCommon_Interface = record - ptrVTable: Pointer; - ptrInstance: PShlComRec; - end; - - TShlComRec = record - ShellExtInit_Interface: TShellExtInit_Interface; - ContextMenu3_Interface: TContextMenu3_Interface; - {fields} - RefCount: LongInt; - // this is owned by the shell after items are added 'n' is used to - // grab menu information directly via id rather than array indexin' - hRootMenu: THandle; - idCmdFirst: Integer; - // most of the memory allocated is on this heap object so HeapDestroy() - // can do most of the cleanup, extremely lazy I know. - hDllHeap: THandle;
- // This is a submenu that recently used contacts are inserted into
- // the contact is inserted twice, once in its normal list (or group) and here
- // Note: These variables are global data, but refered to locally by each instance
- // Do not rely on these variables outside the process enumeration.
- hRecentMenu: THandle;
- RecentCount: Cardinal; // number of added items - // array of all the protocol icons, for every running instance! - ProtoIcons: ^TSlotProtoIconsArray; - ProtoIconsCount: Cardinal; - // maybe null, taken from IShellExtInit_Initalise() and AddRef()'d - // only used if a Miranda instance is actually running and a user - // is selected - pDataObject: PDataObject_Interface; - // DC is used for font metrics and saves on creating and destroying lots of DC handles - // during WM_MEASUREITEM - hMemDC: HDC; - end; - - { this is passed to the enumeration callback so it can process PID's with - main windows by the class name MIRANDANAME loaded with the plugin - and use the IPC stuff between enumerations -- } - - PEnumData = ^TEnumData; - TEnumData = record - Self: PShlComRec; - // autodetected, don't hard code since shells that don't support it - // won't send WM_MEASUREITETM/WM_DRAWITEM at all. - bOwnerDrawSupported: LongBool; - // as per user setting (maybe of multiple Mirandas) - bShouldOwnerDraw: LongBool; - idCmdFirst: Integer; - ipch: PHeaderIPC; - // OpenEvent()'d handle to give each IPC server an object to set signalled - hWaitFor: THandle; - pid: DWORD; // sub-unique value used to make work object name - end; - - procedure FreeGroupTreeAndEmptyGroups(hParentMenu: THandle; pp, p: PGroupNode); - var - q: PGroupNode; - begin - while p <> nil do - begin - q := p^.Right; - if p^.Left <> nil then - begin - FreeGroupTreeAndEmptyGroups(p^.Left^.hMenu, p, p^.Left); - end; //if - if p^.dwItems = 0 then - begin - if pp <> nil then - begin - DeleteMenu(pp^.hMenu, p^.hMenuGroupID, MF_BYCOMMAND) - end else begin - DeleteMenu(hParentMenu, p^.hMenuGroupID, MF_BYCOMMAND); - end; //if - end else begin - // make sure this node's parent know's it exists - if pp <> nil then inc (pp^.dwItems); - end; - Dispose(p); - p := q; - end; - end; - - procedure DecideMenuItemInfo(pct: PSlotIPC; pg: PGroupNode; var mii: TMenuItemInfo; lParam: PEnumData); - var - psd: PMenuDrawInfo; - hDllHeap: THandle; - j, c: Cardinal; - pp: ^TSlotProtoIconsArray; - begin - mii.wID := lParam^.idCmdFirst; - Inc(lParam^.idCmdFirst); - // get the heap object - hDllHeap := lParam^.Self^.hDllHeap; - psd := HeapAlloc(hDllHeap, 0, sizeof(TMenuDrawInfo)); - if pct <> nil then - begin - psd^.cch := pct^.cbStrSection-1; // no null; - psd^.szText := HeapAlloc(hDllHeap, 0, pct^.cbStrSection); - strcpy(psd^.szText, PChar(Integer(pct)+sizeof(TSlotIPC))); - psd^.hContact := pct^.hContact; - psd^.fTypes := [dtContact]; - // find the protocol icon array to use and which status - c := lParam^.Self^.protoIconsCount; - pp := lParam^.Self^.protoIcons; - psd^.hStatusIcon := 0; - while c > 0 do - begin - dec(c); - if (pp[c].hProto = pct^.hProto) and (pp[c].pid = lParam^.pid) then - begin - psd^.hStatusIcon := pp[c].hIcons[pct^.Status - ID_STATUS_OFFLINE]; - psd^.hStatusBitmap := pp[c].hBitmaps[pct^.Status - ID_STATUS_OFFLINE]; - break; - end; - end; //while - psd^.pid := lParam^.pid; - end else if pg <> nil then - begin - // store the given ID - pg^.hMenuGroupID := mii.wID; - // steal the pointer from the group node it should be on the heap - psd^.cch := pg^.cchGroup; - psd^.szText := pg^.szGroup; - psd^.fTypes := [dtGroup]; - end; //if - psd^.wID := mii.wID; - psd^.szProfile := nil; - // store - mii.dwItemData := Integer(psd); - - if ((lParam^.bOwnerDrawSupported) and (lParam^.bShouldOwnerDraw)) then - begin - mii.fType := MFT_OWNERDRAW; - Pointer(mii.dwTypeData) := psd; - end else begin - // normal menu - mii.fType := MFT_STRING; - if pct <> nil then - begin - Integer(mii.dwTypeData) := Integer(pct) + sizeof(TSlotIPC); - end else begin - mii.dwTypeData := pg^.szGroup; - end; - { For Vista + let the system draw the theme and icons, pct = contact associated data } - if VistaOrLater and ( pct <> nil ) and ( psd <> nil) then - begin - mii.fMask := MIIM_BITMAP or MIIM_FTYPE or MIIM_ID or MIIM_DATA or MIIM_STRING; - // BuildSkinIcons() built an array of bitmaps which we can use here - mii.hBmpItem := psd^.hStatusBitmap; - end; - end; //if +
+{$IFDEF FPC}
+{$PACKRECORDS 4}
+{$MODE Delphi}
+{$ENDIF}
+
+interface
+
+uses
+
+ Windows, m_api, shlipc, shlicons;
+
+{$DEFINE COM_STRUCTS}
+{$DEFINE SHLCOM}
+{$INCLUDE shlc.inc}
+{$UNDEF SHLCOM}
+{$UNDEF COM_STRUCTS}
+function DllGetClassObject(const CLSID: TCLSID; const IID: TIID; var Obj): HResult; stdcall;
+function DllCanUnloadNow: HResult; stdcall;
+
+procedure InvokeThreadServer;
+
+procedure CheckRegisterServer;
+
+procedure CheckUnregisterServer;
+
+function RemoveCOMRegistryEntries: HResult;
+
+function ExtractIcon(hInst: THandle; pszExe: PChar; nIndex: Integer): HICON; stdcall;
+ external 'shell32.dll' name 'ExtractIconA';
+
+implementation
+
+var
+
+ dllpublic: record FactoryCount: Integer;
+ ObjectCount: Integer;
+end;
+
+VistaOrLater:
+Boolean;
+
+{$DEFINE COMAPI}
+{$INCLUDE shlc.inc}
+{$UNDEF COMAPI}
+
+const
+
+ IPC_PACKET_SIZE = $1000 * 32;
+ // IPC_PACKET_NAME = 'm.mi.miranda.ipc'; // prior to 1.0.6.6
+ // IPC_PACKET_NAME = 'mi.miranda.IPCServer'; // prior to 2.0.0.9
+ IPC_PACKET_NAME = 'm.mi.miranda.ipc.server';
+
+const
+
+ { Flags returned by IContextMenu*:QueryContextMenu() }
+
+ CMF_NORMAL = $00000000;
+ CMF_DEFAULTONLY = $00000001;
+ CMF_VERBSONLY = $00000002;
+ CMF_EXPLORE = $00000004;
+ CMF_NOVERBS = $00000008;
+ CMF_CANRENAME = $00000010;
+ CMF_NODEFAULT = $00000020;
+ CMF_INCLUDESTATIC = $00000040;
+ CMF_RESERVED = $FFFF0000; { view specific }
+
+ { IContextMenu*:GetCommandString() uType flags }
+
+ GCS_VERBA = $00000000; // canonical verb
+ GCS_HELPTEXTA = $00000001; // help text (for status bar)
+ GCS_VALIDATEA = $00000002; // validate command exists
+ GCS_VERBW = $00000004; // canonical verb (unicode)
+ GC_HELPTEXTW = $00000005; // help text (unicode version)
+ GCS_VALIDATEW = $00000006; // validate command exists (unicode)
+ GCS_UNICODE = $00000004; // for bit testing - Unicode string
+ GCS_VERB = GCS_VERBA; //
+ GCS_HELPTEXT = GCS_HELPTEXTA;
+ GCS_VALIDATE = GCS_VALIDATEA;
+
+type
+
+ { this structure is returned by InvokeCommand() }
+
+ PCMInvokeCommandInfo = ^TCMInvokeCommandInfo;
+
+ TCMInvokeCommandInfo = packed record
+ cbSize: DWORD;
+ fMask: DWORD;
+ hwnd: hwnd;
+ lpVerb: PChar; { maybe index, type cast as Integer }
+ lpParams: PChar;
+ lpDir: PChar;
+ nShow: Integer;
+ dwHotkey: DWORD;
+ HICON: THandle;
+ end;
+
+ { completely stolen from modules.c: 'NameHashFunction' modified slightly }
+
+function StrHash(const szStr: PChar): DWORD; cdecl;
+asm
+ // esi content has to be preserved with basm
+ push esi
+ xor edx,edx
+ xor eax,eax
+ mov esi,szStr
+ mov al,[esi]
+ xor cl,cl
+@@lph_top: // only 4 of 9 instructions in here don't use AL, so optimal pipe use is impossible
+ xor edx,eax
+ inc esi
+ xor eax,eax
+ and cl,31
+ mov al,[esi]
+ add cl,5
+ test al,al
+ rol eax,cl // rol is u-pipe only, but pairable
+ // rol doesn't touch z-flag
+ jnz @@lph_top // 5 clock tick loop. not bad.
+ xor eax,edx
+ pop esi
+end;
+
+function CreateProcessUID(const pid: Cardinal): string;
+var
+ pidrep: string[16];
+begin
+ str(pid, pidrep);
+ Result := Concat('mim.shlext.', pidrep, '$');
+end;
+
+function CreateUID: string;
+var
+ pidrep, tidrep: string[16];
+begin
+ str(GetCurrentProcessId(), pidrep);
+ str(GetCurrentThreadId(), tidrep);
+ Result := Concat('mim.shlext.caller', pidrep, '$', tidrep);
+end;
+
+// FPC doesn't support array[0..n] of Char extended syntax with Str()
+
+function wsprintf(lpOut, lpFmt: PChar; ArgInt: Integer): Integer; cdecl;
+ external 'user32.dll' name 'wsprintfA';
+
+procedure str(i: Integer; S: PChar);
+begin
+ i := wsprintf(S, '%d', i);
+ if i > 2 then
+ PChar(S)[i] := #0;
+end;
+
+{ IShlCom }
+
+type
+
+ PLResult = ^LResult;
+
+ // bare minimum interface of IDataObject, since GetData() is only required.
+
+ PVTable_IDataObject = ^TVTable_IDataObject;
+
+ TVTable_IDataObject = record
+ { IUnknown }
+ QueryInterface: Pointer;
+ AddRef: function(Self: Pointer): Cardinal; stdcall;
+ Release: function(Self: Pointer): Cardinal; stdcall;
+ { IDataObject }
+ GetData: function(Self: Pointer; var formatetcIn: TFormatEtc; var medium: TStgMedium)
+ : HResult; stdcall;
+ GetDataHere: Pointer;
+ QueryGetData: Pointer;
+ GetCanonicalFormatEtc: Pointer;
+ SetData: Pointer;
+ EnumFormatEtc: Pointer;
+ DAdvise: Pointer;
+ DUnadvise: Pointer;
+ EnumDAdvise: Pointer;
+ end;
+
+ PDataObject_Interface = ^TDataObject_Interface;
+
+ TDataObject_Interface = record
+ ptrVTable: PVTable_IDataObject;
+ end;
+
+ { TShlComRec inherits from different interfaces with different function tables
+ all "compiler magic" is lost in this case, but it's pretty easy to return
+ a different function table for each interface, IContextMenu is returned
+ as IContextMenu'3' since it inherits from '2' and '1' }
+
+ PVTable_IShellExtInit = ^TVTable_IShellExtInit;
+
+ TVTable_IShellExtInit = record
+ { IUnknown }
+ QueryInterface: Pointer;
+ AddRef: Pointer;
+ Release: Pointer;
+ { IShellExtInit }
+ Initialise: Pointer;
+ end;
+
+ PShlComRec = ^TShlComRec;
+ PShellExtInit_Interface = ^TShellExtInit_Interface;
+
+ TShellExtInit_Interface = record
+ { pointer to function table }
+ ptrVTable: PVTable_IShellExtInit;
+ { instance data }
+ ptrInstance: PShlComRec;
+ { function table itself }
+ vTable: TVTable_IShellExtInit;
+ end;
+
+ PVTable_IContextMenu3 = ^TVTable_IContextMenu3;
+
+ TVTable_IContextMenu3 = record
+ { IUnknown }
+ QueryInterface: Pointer;
+ AddRef: Pointer;
+ Release: Pointer;
+ { IContextMenu }
+ QueryContextMenu: Pointer;
+ InvokeCommand: Pointer;
+ GetCommandString: Pointer;
+ { IContextMenu2 }
+ HandleMenuMsg: Pointer;
+ { IContextMenu3 }
+ HandleMenuMsg2: Pointer;
+ end;
+
+ PContextMenu3_Interface = ^TContextMenu3_Interface;
+
+ TContextMenu3_Interface = record
+ ptrVTable: PVTable_IContextMenu3;
+ ptrInstance: PShlComRec;
+ vTable: TVTable_IContextMenu3;
+ end;
+
+ PCommon_Interface = ^TCommon_Interface;
+
+ TCommon_Interface = record
+ ptrVTable: Pointer;
+ ptrInstance: PShlComRec;
+ end;
+
+ TShlComRec = record
+ ShellExtInit_Interface: TShellExtInit_Interface;
+ ContextMenu3_Interface: TContextMenu3_Interface;
+ { fields }
+ RefCount: LongInt;
+ // this is owned by the shell after items are added 'n' is used to
+ // grab menu information directly via id rather than array indexin'
+ hRootMenu: THandle;
+ idCmdFirst: Integer;
+ // most of the memory allocated is on this heap object so HeapDestroy()
+ // can do most of the cleanup, extremely lazy I know.
+ hDllHeap: THandle;
+ // This is a submenu that recently used contacts are inserted into
+ // the contact is inserted twice, once in its normal list (or group) and here
+ // Note: These variables are global data, but refered to locally by each instance
+ // Do not rely on these variables outside the process enumeration.
+ hRecentMenu: THandle;
+ RecentCount: Cardinal; // number of added items
+ // array of all the protocol icons, for every running instance!
+ ProtoIcons: ^TSlotProtoIconsArray;
+ ProtoIconsCount: Cardinal;
+ // maybe null, taken from IShellExtInit_Initalise() and AddRef()'d
+ // only used if a Miranda instance is actually running and a user
+ // is selected
+ pDataObject: PDataObject_Interface;
+ // DC is used for font metrics and saves on creating and destroying lots of DC handles
+ // during WM_MEASUREITEM
+ hMemDC: HDC;
+ end;
+
+ { this is passed to the enumeration callback so it can process PID's with
+ main windows by the class name MIRANDANAME loaded with the plugin
+ and use the IPC stuff between enumerations -- }
+
+ PEnumData = ^TEnumData;
+
+ TEnumData = record
+ Self: PShlComRec;
+ // autodetected, don't hard code since shells that don't support it
+ // won't send WM_MEASUREITETM/WM_DRAWITEM at all.
+ bOwnerDrawSupported: LongBool;
+ // as per user setting (maybe of multiple Mirandas)
+ bShouldOwnerDraw: LongBool;
+ idCmdFirst: Integer;
+ ipch: PHeaderIPC;
+ // OpenEvent()'d handle to give each IPC server an object to set signalled
+ hWaitFor: THandle;
+ pid: DWORD; // sub-unique value used to make work object name
+ end;
+
+procedure FreeGroupTreeAndEmptyGroups(hParentMenu: THandle; pp, p: PGroupNode);
+var
+ q: PGroupNode;
+begin
+ while p <> nil do
+ begin
+ q := p^.Right;
+ if p^.Left <> nil then
+ begin
+ FreeGroupTreeAndEmptyGroups(p^.Left^.hMenu, p, p^.Left);
+ end; // if
+ if p^.dwItems = 0 then
+ begin
+ if pp <> nil then
+ begin
+ DeleteMenu(pp^.hMenu, p^.hMenuGroupID, MF_BYCOMMAND)
+ end
+ else
+ begin
+ DeleteMenu(hParentMenu, p^.hMenuGroupID, MF_BYCOMMAND);
+ end; // if
+ end
+ else
+ begin
+ // make sure this node's parent know's it exists
+ if pp <> nil then
+ inc(pp^.dwItems);
+ end;
+ Dispose(p);
+ p := q;
+ end;
+end;
+
+procedure DecideMenuItemInfo(pct: PSlotIPC; pg: PGroupNode; var mii: TMenuItemInfo;
+ lParam: PEnumData);
+var
+ psd: PMenuDrawInfo;
+ hDllHeap: THandle;
+ j, c: Cardinal;
+ pp: ^TSlotProtoIconsArray;
+begin
+ mii.wID := lParam^.idCmdFirst;
+ inc(lParam^.idCmdFirst);
+ // get the heap object
+ hDllHeap := lParam^.Self^.hDllHeap;
+ psd := HeapAlloc(hDllHeap, 0, sizeof(TMenuDrawInfo));
+ if pct <> nil then
+ begin
+ psd^.cch := pct^.cbStrSection - 1; // no null;
+ psd^.szText := HeapAlloc(hDllHeap, 0, pct^.cbStrSection);
+ lstrcpya(psd^.szText, PChar(Integer(pct) + sizeof(TSlotIPC)));
+ psd^.hContact := pct^.hContact;
+ psd^.fTypes := [dtContact];
+ // find the protocol icon array to use and which status
+ c := lParam^.Self^.ProtoIconsCount;
+ pp := lParam^.Self^.ProtoIcons;
+ psd^.hStatusIcon := 0;
+ while c > 0 do
+ begin
+ dec(c);
+ if (pp[c].hProto = pct^.hProto) and (pp[c].pid = lParam^.pid) then
+ begin
+ psd^.hStatusIcon := pp[c].hIcons[pct^.Status - ID_STATUS_OFFLINE];
+ psd^.hStatusBitmap := pp[c].hBitmaps[pct^.Status - ID_STATUS_OFFLINE];
+ break;
+ end;
+ end; // while
+ psd^.pid := lParam^.pid;
+ end
+ else if pg <> nil then
+ begin
+ // store the given ID
+ pg^.hMenuGroupID := mii.wID;
+ // steal the pointer from the group node it should be on the heap
+ psd^.cch := pg^.cchGroup;
+ psd^.szText := pg^.szGroup;
+ psd^.fTypes := [dtGroup];
+ end; // if
+ psd^.wID := mii.wID;
+ psd^.szProfile := nil;
+ // store
+ mii.dwItemData := Integer(psd);
+
+ if ((lParam^.bOwnerDrawSupported) and (lParam^.bShouldOwnerDraw)) then
+ begin
+ mii.fType := MFT_OWNERDRAW;
+ Pointer(mii.dwTypeData) := psd;
+ end
+ else
+ begin
+ // normal menu
+ mii.fType := MFT_STRING;
+ if pct <> nil then
+ begin
+ int_ptr(mii.dwTypeData) := int_ptr(pct) + sizeof(TSlotIPC);
+ end
+ else
+ begin
+ mii.dwTypeData := pg^.szGroup;
+ end;
+ { For Vista + let the system draw the theme and icons, pct = contact associated data }
+ if VistaOrLater and (pct <> nil) and (psd <> nil) then
+ begin
+ mii.fMask := MIIM_BITMAP or MIIM_FTYPE or MIIM_ID or MIIM_DATA or MIIM_STRING;
+ // BuildSkinIcons() built an array of bitmaps which we can use here
+ mii.hBmpItem := psd^.hStatusBitmap;
+ end;
+ end; // if
+end;
+
+// must be called after DecideMenuItemInfo()
+procedure BuildMRU(pct: PSlotIPC; var mii: TMenuItemInfo; lParam: PEnumData);
+begin
+ if pct^.MRU > 0 then
+ begin
+ inc(lParam^.Self^.RecentCount);
+ // lParam^.Self == pointer to object data
+ InsertMenuitem(lParam^.Self^.hRecentMenu, $FFFFFFFF, True, mii);
+ end;
+end;
+
+procedure BuildContactTree(group: PGroupNode; lParam: PEnumData);
+label
+ grouploop;
+var
+ pct: PSlotIPC;
+ pg, px: PGroupNode;
+ str: TStrTokRec;
+ sz: PChar;
+ Hash: Cardinal;
+ Depth: Cardinal;
+ mii: TMenuItemInfo;
+begin
+ // set up the menu item
+ mii.cbSize := sizeof(TMenuItemInfo);
+ mii.fMask := MIIM_ID or MIIM_TYPE or MIIM_DATA;
+ // set up the scanner
+ str.szSet := ['\'];
+ str.bSetTerminator := False;
+ // go thru all the contacts
+ pct := lParam^.ipch^.ContactsBegin;
+ while (pct <> nil) and (pct^.cbSize = sizeof(TSlotIPC)) and (pct^.fType = REQUEST_CONTACTS) do
+ begin
+ if pct^.hGroup <> 0 then
+ begin
+ // at the end of the slot header is the contact's display name
+ // and after a double NULL char there is the group string, which has the full path of the group
+ // this must be tokenised at '\' and we must walk the in memory group tree til we find our group
+ // this is faster than the old version since we only ever walk one or at most two levels of the tree
+ // per tokenised section, and it doesn't matter if two levels use the same group name (which is valid)
+ // as the tokens processed is equatable to depth of the tree
+ str.szStr := PChar(Integer(pct) + sizeof(TSlotIPC) + pct^.cbStrSection + 1);
+ sz := StrTok(str);
+ // restore the root
+ pg := group;
+ Depth := 0;
+ while sz <> nil do
+ begin
+ Hash := StrHash(sz);
+ // find this node within
+ while pg <> nil do
+ begin
+ // does this node have the right hash and the right depth?
+ if (Hash = pg^.Hash) and (Depth = pg^.Depth) then
+ break;
+ // each node may have a left pointer going to a sub tree
+ // the path syntax doesn't know if a group is a group at the same level
+ // or a nested one, which means the search node can be anywhere
+ px := pg^.Left;
+ if px <> nil then
+ begin
+ // keep searching this level
+ while px <> nil do
+ begin
+ if (Hash = px^.Hash) and (Depth = px^.Depth) then
+ begin
+ // found the node we're looking for at the next level to pg, px is now pq for next time
+ pg := px;
+ goto grouploop;
+ end; // if
+ px := px^.Right;
+ end; // if
+ end; // if
+ pg := pg^.Right;
+ end; // while
+ grouploop:
+ inc(Depth);
+ // process next token
+ sz := StrTok(str);
+ end; // while
+ // tokenisation finished, if pg <> nil then the group is found
+ if pg <> nil then
+ begin
+ DecideMenuItemInfo(pct, nil, mii, lParam);
+ BuildMRU(pct, mii, lParam);
+ InsertMenuitem(pg^.hMenu, $FFFFFFFF, True, mii);
+ inc(pg^.dwItems);
+ end;
+ end; // if
+ pct := pct^.Next;
+ end; // while
+end;
+
+procedure BuildMenuGroupTree(p: PGroupNode; lParam: PEnumData; hLastMenu: hMenu);
+var
+ mii: TMenuItemInfo;
+begin
+ mii.cbSize := sizeof(TMenuItemInfo);
+ mii.fMask := MIIM_ID or MIIM_DATA or MIIM_TYPE or MIIM_SUBMENU;
+ // go thru each group and create a menu for it adding submenus too.
+ while p <> nil do
+ begin
+ mii.hSubMenu := CreatePopupMenu();
+ if p^.Left <> nil then
+ BuildMenuGroupTree(p^.Left, lParam, mii.hSubMenu);
+ p^.hMenu := mii.hSubMenu;
+ DecideMenuItemInfo(nil, p, mii, lParam);
+ InsertMenuitem(hLastMenu, $FFFFFFFF, True, mii);
+ p := p^.Right;
+ end; // while
+end;
+
+{ this callback is triggered by the menu code and IPC is already taking place,
+ just the transfer type+data needs to be setup }
+function ClearMRUIPC(pipch: PHeaderIPC; // IPC header info, already mapped
+ hWorkThreadEvent: THandle; // event object being waited on on miranda thread
+ hAckEvent: THandle; // ack event object that has been created
+ psd: PMenuDrawInfo // command/draw info
+ ): Integer; stdcall;
+begin
+ Result := S_OK;
+ ipcPrepareRequests(IPC_PACKET_SIZE, pipch, REQUEST_CLEARMRU);
+ ipcSendRequest(hWorkThreadEvent, hAckEvent, pipch, 100);
+end;
+
+procedure RemoveCheckmarkSpace(hMenu: hMenu);
+const
+ MIM_STYLE = $00000010;
+ MNS_CHECKORBMP = $4000000;
+type
+ TMENUINFO = record
+ cbSize: DWORD;
+ fMask: DWORD;
+ dwStyle: DWORD;
+ cyMax: LongInt;
+ hbrBack: THandle;
+ dwContextHelpID: DWORD;
+ dwMenuData: Pointer;
+ end;
+var
+ SetMenuInfo: function(hMenu: hMenu; var mi: TMENUINFO): Boolean; stdcall;
+ mi: TMENUINFO;
+begin
+ if not VistaOrLater then
+ Exit;
+ SetMenuInfo := GetProcAddress(GetModuleHandle('user32'), 'SetMenuInfo');
+ if @SetMenuInfo = nil then
+ Exit;
+ mi.cbSize := sizeof(mi);
+ mi.fMask := MIM_STYLE;
+ mi.dwStyle := MNS_CHECKORBMP;
+ SetMenuInfo(hMenu, mi);
+end;
+
+procedure BuildMenus(lParam: PEnumData);
+{$DEFINE SHL_IDC}
+{$DEFINE SHL_KEYS}
+{$INCLUDE shlc.inc}
+{$UNDEF SHL_KEYS}
+{$UNDEF SHL_IDC}
+var
+ hBaseMenu: hMenu;
+ hGroupMenu: hMenu;
+ pg: PSlotIPC;
+ szProf: PChar;
+ mii: TMenuItemInfo;
+ j: TGroupNodeList;
+ p, q: PGroupNode;
+ Depth, Hash: Cardinal;
+ Token: PChar;
+ tk: TStrTokRec;
+ szBuf: PChar;
+ hDllHeap: THandle;
+ psd: PMenuDrawInfo;
+ c: Cardinal;
+ pp: ^TSlotProtoIconsArray;
+begin
+ ZeroMemory(@mii, sizeof(mii));
+ hDllHeap := lParam^.Self^.hDllHeap;
+ hBaseMenu := lParam^.Self^.hRootMenu;
+ // build an in memory tree of the groups
+ pg := lParam^.ipch^.GroupsBegin;
+ tk.szSet := ['\'];
+ tk.bSetTerminator := False;
+ j.First := nil;
+ j.Last := nil;
+ while pg <> nil do
+ begin
+ if (pg^.cbSize <> sizeof(TSlotIPC)) or (pg^.fType <> REQUEST_GROUPS) then
+ break;
+ Depth := 0;
+ p := j.First; // start at root again
+ // get the group
+ int_ptr(tk.szStr) := (int_ptr(pg) + sizeof(TSlotIPC));
+ // find each word between \ and create sub groups if needed.
+ Token := StrTok(tk);
+ while Token <> nil do
+ begin
+ Hash := StrHash(Token);
+ // if the (sub)group doesn't exist, create it.
+ q := FindGroupNode(p, Hash, Depth);
+ if q = nil then
+ begin
+ q := AllocGroupNode(@j, p, Depth);
+ q^.Depth := Depth;
+ // this is the hash of this group node, but it can be anywhere
+ // i.e. Foo\Foo this is because each node has a different depth
+ // trouble is contacts don't come with depths!
+ q^.Hash := Hash;
+ // don't assume that pg^.hGroup's hash is valid for this token
+ // since it maybe Miranda\Blah\Blah and we have created the first node
+ // which maybe Miranda, thus giving the wrong hash
+ // since "Miranda" can be a group of it's own and a full path
+ q^.cchGroup := lstrlena(Token);
+ q^.szGroup := HeapAlloc(hDllHeap, 0, q^.cchGroup + 1);
+ lstrcpya(q^.szGroup, Token);
+ q^.dwItems := 0;
+ end;
+ p := q;
+ inc(Depth);
+ Token := StrTok(tk);
+ end; // while
+ pg := pg^.Next;
+ end; // while
+ // build the menus inserting into hGroupMenu which will be a submenu of
+ // the instance menu item. e.g. Miranda -> [Groups ->] contacts
+ hGroupMenu := CreatePopupMenu();
+
+ // allocate MRU menu, this will be associated with the higher up menu
+ // so doesn't need to be freed (unless theres no MRUs items attached)
+ // This menu is per process but the handle is stored globally (like a stack)
+ lParam^.Self^.hRecentMenu := CreatePopupMenu();
+ lParam^.Self^.RecentCount := 0;
+ // create group menus only if they exist!
+ if lParam^.ipch^.GroupsBegin <> nil then
+ begin
+ BuildMenuGroupTree(j.First, lParam, hGroupMenu);
+ // add contacts that have a group somewhere
+ BuildContactTree(j.First, lParam);
+ end;
+ //
+ mii.cbSize := sizeof(TMenuItemInfo);
+ mii.fMask := MIIM_ID or MIIM_TYPE or MIIM_DATA;
+ // add all the contacts that have no group (which maybe all of them)
+ pg := lParam^.ipch^.ContactsBegin;
+ while pg <> nil do
+ begin
+ if (pg^.cbSize <> sizeof(TSlotIPC)) or (pg^.fType <> REQUEST_CONTACTS) then
+ break;
+ if pg^.hGroup = 0 then
+ begin
+ DecideMenuItemInfo(pg, nil, mii, lParam);
+ BuildMRU(pg, mii, lParam);
+ InsertMenuitem(hGroupMenu, $FFFFFFFF, True, mii);
+ end; // if
+ pg := pg^.Next;
+ end; // while
+
+ // insert MRU menu as a submenu of the contact menu only if
+ // the MRU list has been created, the menu popup will be deleted by itself
+ if lParam^.Self^.RecentCount > 0 then
+ begin
+
+ // insert seperator and 'clear list' menu
+ mii.fType := MFT_SEPARATOR;
+ mii.fMask := MIIM_TYPE;
+ InsertMenuitem(lParam^.Self^.hRecentMenu, $FFFFFFFF, True, mii);
+
+ // insert 'clear MRU' item and setup callback
+ mii.fMask := MIIM_TYPE or MIIM_ID or MIIM_DATA;
+ mii.wID := lParam^.idCmdFirst;
+ inc(lParam^.idCmdFirst);
+ mii.fType := MFT_STRING;
+ mii.dwTypeData := lParam^.ipch^.ClearEntries; // "Clear entries"
+ // allocate menu substructure
+ psd := HeapAlloc(hDllHeap, 0, sizeof(TMenuDrawInfo));
+ psd^.fTypes := [dtCommand];
+ psd^.MenuCommandCallback := @ClearMRUIPC;
+ psd^.wID := mii.wID;
+ // this is needed because there is a clear list command per each process.
+ psd^.pid := lParam^.pid;
+ mii.dwItemData := Integer(psd);
+ InsertMenuitem(lParam^.Self^.hRecentMenu, $FFFFFFFF, True, mii);
+
+ // insert MRU submenu into group menu (with) ownerdraw support as needed
+ psd := HeapAlloc(hDllHeap, 0, sizeof(TMenuDrawInfo));
+ psd^.szProfile := 'MRU';
+ psd^.fTypes := [dtGroup];
+ // the IPC string pointer wont be around forever, must make a copy
+ psd^.cch := strlen(lParam^.ipch^.MRUMenuName);
+ psd^.szText := HeapAlloc(hDllHeap, 0, psd^.cch + 1);
+ lstrcpyn(psd^.szText, lParam^.ipch^.MRUMenuName, sizeof(lParam^.ipch^.MRUMenuName) - 1);
+
+ mii.dwItemData := Integer(psd);
+ if (lParam^.bOwnerDrawSupported) and (lParam^.bShouldOwnerDraw) then
+ begin
+ mii.fType := MFT_OWNERDRAW;
+ Pointer(mii.dwTypeData) := psd;
+ end
+ else
+ begin
+ mii.dwTypeData := lParam^.ipch^.MRUMenuName; // 'Recent';
end;
-
- // must be called after DecideMenuItemInfo()
- procedure BuildMRU(pct: PSlotIPC; var mii: TMenuItemInfo; lParam: PEnumData);
- begin
- if pct^.MRU > 0 then
- begin
- Inc(lParam^.Self^.RecentCount);
- // lParam^.Self == pointer to object data
- InsertMenuitem(lParam^.Self^.hRecentMenu, $FFFFFFFF, True, mii);
- end;
- end;
- - procedure BuildContactTree(group: PGroupNode; lParam: PEnumData); - label - grouploop; - var - pct: PSlotIPC; - pg, px: PGroupNode; - str: TStrTokRec; - sz: PChar; - Hash: Cardinal; - Depth: Cardinal; - mii: TMenuItemInfo; - begin - // set up the menu item - mii.cbSize := sizeof(TMenuItemInfo); - mii.fMask := MIIM_ID or MIIM_TYPE or MIIM_DATA; - // set up the scanner - str.szSet := ['\']; - str.bSetTerminator := False; - // go thru all the contacts - pct := lParam^.ipch^.ContactsBegin; - while (pct <> nil) and (pct^.cbSize=sizeof(TSlotIPC)) and (pct^.fType=REQUEST_CONTACTS) do - begin - if pct^.hGroup <> 0 then - begin - // at the end of the slot header is the contact's display name - // and after a double NULL char there is the group string, which has the full path of the group - // this must be tokenised at '\' and we must walk the in memory group tree til we find our group - // this is faster than the old version since we only ever walk one or at most two levels of the tree - // per tokenised section, and it doesn't matter if two levels use the same group name (which is valid) - // as the tokens processed is equatable to depth of the tree - str.szStr := PChar(Integer(pct)+sizeof(TSlotIPC)+pct^.cbStrSection+1); - sz := StrTok(str); - // restore the root - pg := group; - Depth := 0; - while sz <> nil do - begin - Hash := StrHash(sz); - // find this node within - while pg <> nil do - begin - // does this node have the right hash and the right depth? - if (Hash = pg^.Hash) and (Depth = pg^.Depth) then Break; - // each node may have a left pointer going to a sub tree - // the path syntax doesn't know if a group is a group at the same level - // or a nested one, which means the search node can be anywhere - px := pg^.Left; - if px <> nil then - begin - // keep searching this level - while px <> nil do - begin - if (hash = px^.Hash) and (Depth = px^.Depth) then - begin - // found the node we're looking for at the next level to pg, px is now pq for next time - pg := px; - goto grouploop; - end; //if - px := px^.Right; - end; //if - end; //if - pg := pg^.Right; - end; //while - grouploop: - inc (Depth); - // process next token - sz := StrTok(str); - end; //while - // tokenisation finished, if pg <> nil then the group is found - if pg <> nil then - begin - DecideMenuItemInfo(pct, nil, mii, lParam);
- BuildMRU(pct, mii, lParam); - InsertMenuitem(pg^.hMenu, $FFFFFFFF,True, mii); - Inc(pg^.dwItems); - end; - end; //if - pct := pct^.Next; - end; //while - end; - - procedure BuildMenuGroupTree(p: PGroupNode; lParam: PEnumData; hLastMenu: HMENU); - var - mii: TMenuItemInfo; - begin - mii.cbSize := sizeof(TMenuItemInfo); - mii.fMask := MIIM_ID or MIIM_DATA or MIIM_TYPE or MIIM_SUBMENU; - // go thru each group and create a menu for it adding submenus too. - while p <> nil do - begin - mii.hSubMenu := CreatePopupMenu(); - if p^.Left <> nil then BuildMenuGroupTree(p^.Left, lParam, mii.hSubMenu); - p^.hMenu := mii.hSubMenu; - DecideMenuItemInfo(nil, P, mii, lParam); - InsertMenuItem(hLastMenu, $FFFFFFFF, True, mii); - p := p^.Right; - end; //while + mii.wID := lParam^.idCmdFirst;
+ inc(lParam^.idCmdFirst);
+ mii.fMask := MIIM_TYPE or MIIM_SUBMENU or MIIM_DATA or MIIM_ID;
+ mii.hSubMenu := lParam^.Self^.hRecentMenu;
+ InsertMenuitem(hGroupMenu, 0, True, mii);
+ end
+ else
+ begin
+ // no items were attached to the MRU, delete the MRU menu
+ DestroyMenu(lParam^.Self^.hRecentMenu);
+ lParam^.Self^.hRecentMenu := 0;
+ end;
+
+ // allocate display info/memory for "Miranda" string
+
+ mii.cbSize := sizeof(TMenuItemInfo);
+ mii.fMask := MIIM_ID or MIIM_DATA or MIIM_TYPE or MIIM_SUBMENU;
+ if VistaOrLater then
+ begin
+ mii.fMask := MIIM_ID or MIIM_DATA or MIIM_FTYPE or MIIM_SUBMENU or MIIM_STRING or
+ MIIM_BITMAP;
+ end;
+ mii.hSubMenu := hGroupMenu;
+
+ // by default, the menu will have space for icons and checkmarks (on Vista+) and we don't need this
+ RemoveCheckmarkSpace(hGroupMenu);
+
+ psd := HeapAlloc(hDllHeap, 0, sizeof(TMenuDrawInfo));
+ psd^.cch := strlen(lParam^.ipch^.MirandaName);
+ psd^.szText := HeapAlloc(hDllHeap, 0, psd^.cch + 1);
+ lstrcpyn(psd^.szText, lParam^.ipch^.MirandaName, sizeof(lParam^.ipch^.MirandaName) - 1);
+ // there may not be a profile name
+ pg := lParam^.ipch^.DataPtr;
+ psd^.szProfile := nil;
+ if ((pg <> nil) and (pg^.Status = STATUS_PROFILENAME)) then
+ begin
+ psd^.szProfile := HeapAlloc(hDllHeap, 0, pg^.cbStrSection);
+ lstrcpya(psd^.szProfile, PChar(Integer(pg) + sizeof(TSlotIPC)));
+ end; // if
+ // owner draw menus need ID's
+ mii.wID := lParam^.idCmdFirst;
+ inc(lParam^.idCmdFirst);
+ psd^.fTypes := [dtEntry];
+ psd^.wID := mii.wID;
+ psd^.hContact := 0;
+ // get Miranda's icon or bitmap
+ c := lParam^.Self^.ProtoIconsCount;
+ pp := lParam^.Self^.ProtoIcons;
+ while c > 0 do
+ begin
+ dec(c);
+ if (pp[c].pid = lParam^.pid) and (pp[c].hProto = 0) then
+ begin
+ // either of these can be 0
+ psd^.hStatusIcon := pp[c].hIcons[0];
+ mii.hBmpItem := pp[c].hBitmaps[0];
+ break;
+ end; // if
+ end; // while
+ mii.dwItemData := Integer(psd);
+ if ((lParam^.bOwnerDrawSupported) and (lParam^.bShouldOwnerDraw)) then
+ begin
+ mii.fType := MFT_OWNERDRAW;
+ Pointer(mii.dwTypeData) := psd;
+ end
+ else
+ begin
+ mii.fType := MFT_STRING;
+ mii.dwTypeData := lParam^.ipch^.MirandaName;
+ mii.cch := sizeof(lParam^.ipch^.MirandaName) - 1;
+ end;
+ // add it all
+ InsertMenuitem(hBaseMenu, 0, True, mii);
+ // free the group tree
+ FreeGroupTreeAndEmptyGroups(hGroupMenu, nil, j.First);
+end;
+
+procedure BuildSkinIcons(lParam: PEnumData);
+var
+ pct: PSlotIPC;
+ p, d: PSlotProtoIcons;
+ Self: PShlComRec;
+ j: Cardinal;
+ imageFactory: PImageFactory_Interface;
+begin
+ pct := lParam^.ipch^.NewIconsBegin;
+ Self := lParam^.Self;
+ while (pct <> nil) do
+ begin
+ if (pct^.cbSize <> sizeof(TSlotIPC)) or (pct^.fType <> REQUEST_NEWICONS) then
+ break;
+ int_ptr(p) := int_ptr(pct) + sizeof(TSlotIPC);
+ ReAllocMem(Self^.ProtoIcons, (Self^.ProtoIconsCount + 1) * sizeof(TSlotProtoIcons));
+ d := @Self^.ProtoIcons[Self^.ProtoIconsCount];
+ CopyMemory(d, p, sizeof(TSlotProtoIcons));
+
+ {
+ If using Vista (or later), clone all the icons into bitmaps and keep these around,
+ if using anything older, just use the default code, the bitmaps (and or icons) will be freed
+ with the shell object.
+ }
+
+ imageFactory := nil;
+
+ for j := 0 to 9 do
+ begin
+ if imageFactory = nil then
+ imageFactory := ARGB_GetWorker();
+ if VistaOrLater then
+ begin
+ d^.hBitmaps[j] := ARGB_BitmapFromIcon(imageFactory, Self^.hMemDC, p^.hIcons[j]);
+ d^.hIcons[j] := 0;
+ end
+ else
+ begin
+ d^.hBitmaps[j] := 0;
+ d^.hIcons[j] := CopyIcon(p^.hIcons[j]);
+ end;
+ end;
+
+ if imageFactory <> nil then
+ begin
+ imageFactory^.ptrVTable^.Release(imageFactory);
+ imageFactory := nil;
+ end;
+
+ inc(Self^.ProtoIconsCount);
+ pct := pct^.Next;
+ end;
+end;
+
+function ProcessRequest(hwnd: hwnd; lParam: PEnumData): BOOL; stdcall;
+var
+ pid: Integer;
+ hMirandaWorkEvent: THandle;
+ replyBits: Integer;
+ hScreenDC: THandle;
+ szBuf: array [0 .. MAX_PATH] of Char;
+begin
+ Result := True;
+ pid := 0;
+ GetWindowThreadProcessId(hwnd, @pid);
+ If pid <> 0 then
+ begin
+ // old system would get a window's pid and the module handle that created it
+ // and try to OpenEvent() a event object name to it (prefixed with a string)
+ // this was fine for most Oses (not the best way) but now actually compares
+ // the class string (a bit slower) but should get rid of those bugs finally.
+ hMirandaWorkEvent := OpenEvent(EVENT_ALL_ACCESS, False, PChar(CreateProcessUID(pid)));
+ if (hMirandaWorkEvent <> 0) then
+ begin
+ GetClassName(hwnd, szBuf, sizeof(szBuf));
+ if lstrcmp(szBuf, MirandaName) <> 0 then
+ begin
+ // opened but not valid.
+ CloseHandle(hMirandaWorkEvent);
+ Exit;
+ end; // if
+ end; // if
+ { If the event object exists, then a shlext.dll running in the instance must of created it. }
+ If hMirandaWorkEvent <> 0 then
+ begin
+ { prep the request }
+ ipcPrepareRequests(IPC_PACKET_SIZE, lParam^.ipch, REQUEST_ICONS or REQUEST_GROUPS or
+ REQUEST_CONTACTS or REQUEST_NEWICONS);
+ // slots will be in the order of icon data, groups then contacts, the first
+ // slot will contain the profile name
+ replyBits := ipcSendRequest(hMirandaWorkEvent, lParam^.hWaitFor, lParam^.ipch, 1000);
+ { replyBits will be REPLY_FAIL if the wait timed out, or it'll be the request
+ bits as sent or a series of *_NOTIMPL bits where the request bit were, if there are no
+ contacts to speak of, then don't bother showing this instance of Miranda }
+ if (replyBits <> REPLY_FAIL) and (lParam^.ipch^.ContactsBegin <> nil) then
+ begin
+ // load the address again, the server side will always overwrite it
+ lParam^.ipch^.pClientBaseAddress := lParam^.ipch;
+ // fixup all the pointers to be relative to the memory map
+ // the base pointer of the client side version of the mapped file
+ ipcFixupAddresses(False, lParam^.ipch);
+ // store the PID used to create the work event object
+ // that got replied to -- this is needed since each contact
+ // on the final menu maybe on a different instance and another OpenEvent() will be needed.
+ lParam^.pid := pid;
+ // check out the user options from the server
+ lParam^.bShouldOwnerDraw := (lParam^.ipch^.dwFlags and HIPC_NOICONS) = 0;
+ // process the icons
+ BuildSkinIcons(lParam);
+ // process other replies
+ BuildMenus(lParam);
+ end;
+ { close the work object }
+ CloseHandle(hMirandaWorkEvent);
+ end; // if
+ end; // if
+end;
+
+function TShlComRec_QueryInterface(Self: PCommon_Interface; const IID: TIID; var Obj)
+ : HResult; stdcall;
+begin
+ Pointer(Obj) := nil;
+ { IShellExtInit is given when the TShlRec is created }
+ if IsEqualIID(IID, IID_IContextMenu) or IsEqualIID(IID, IID_IContextMenu2) or
+ IsEqualIID(IID, IID_IContextMenu3) then
+ begin
+ with Self^.ptrInstance^ do
+ begin
+ Pointer(Obj) := @ContextMenu3_Interface;
+ inc(RefCount);
+ end; { with }
+ Result := S_OK;
+ end
+ else
+ begin
+ // under XP, it may ask for IShellExtInit again, this fixes the -double- click to see menus issue
+ // which was really just the object not being created
+ if IsEqualIID(IID, IID_IShellExtInit) then
+ begin
+ with Self^.ptrInstance^ do
+ begin
+ Pointer(Obj) := @ShellExtInit_Interface;
+ inc(RefCount);
+ end; // if
+ Result := S_OK;
+ end
+ else
+ begin
+ Result := CLASS_E_CLASSNOTAVAILABLE;
+ end; // if
+ end; // if
+end;
+
+function TShlComRec_AddRef(Self: PCommon_Interface): LongInt; stdcall;
+begin
+ with Self^.ptrInstance^ do
+ begin
+ inc(RefCount);
+ Result := RefCount;
+ end; { with }
+end;
+
+function TShlComRec_Release(Self: PCommon_Interface): LongInt; stdcall;
+var
+ j, c: Cardinal;
+begin
+ with Self^.ptrInstance^ do
+ begin
+ dec(RefCount);
+ Result := RefCount;
+ If RefCount = 0 then
+ begin
+ // time to go byebye.
+ with Self^.ptrInstance^ do
+ begin
+ // Note MRU menu is associated with a window (indirectly) so windows will free it.
+ // free icons!
+ if ProtoIcons <> nil then
+ begin
+ c := ProtoIconsCount;
+ while c > 0 do
+ begin
+ dec(c);
+ for j := 0 to 9 do
+ begin
+ with ProtoIcons[c] do
+ begin
+ if hIcons[j] <> 0 then
+ DestroyIcon(hIcons[j]);
+ if hBitmaps[j] <> 0 then
+ DeleteObject(hBitmaps[j]);
+ end;
+ end;
+ end;
+ FreeMem(ProtoIcons);
+ ProtoIcons := nil;
+ end; // if
+ // free IDataObject reference if pointer exists
+ if pDataObject <> nil then
+ begin
+ pDataObject^.ptrVTable^.Release(pDataObject);
+ end; // if
+ pDataObject := nil;
+ // free the heap and any memory allocated on it
+ HeapDestroy(hDllHeap);
+ // destroy the DC
+ if hMemDC <> 0 then
+ DeleteDC(hMemDC);
+ end; // with
+ // free the instance (class record) created
+ Dispose(Self^.ptrInstance);
+ dec(dllpublic.ObjectCount);
+ end; { if }
+ end; { with }
+end;
+
+function TShlComRec_Initialise(Self: PContextMenu3_Interface; pidLFolder: Pointer;
+ DObj: PDataObject_Interface; hKeyProdID: HKEY): HResult; stdcall;
+begin
+ // DObj is a pointer to an instance of IDataObject which is a pointer itself
+ // it contains a pointer to a function table containing the function pointer
+ // address of GetData() - the instance data has to be passed explicitly since
+ // all compiler magic has gone.
+ with Self^.ptrInstance^ do
+ begin
+ if DObj <> nil then
+ begin
+ Result := S_OK;
+ // if an instance already exists, free it.
+ if pDataObject <> nil then
+ pDataObject^.ptrVTable^.Release(pDataObject);
+ // store the new one and AddRef() it
+ pDataObject := DObj;
+ pDataObject^.ptrVTable^.AddRef(pDataObject);
+ end
+ else
+ begin
+ Result := E_INVALIDARG;
+ end; // if
+ end; // if
+end;
+
+function MAKE_HRESULT(Severity, Facility, Code: Integer): HResult;
+{$IFDEF FPC}
+inline;
+{$ENDIF}
+begin
+ Result := (Severity shl 31) or (Facility shl 16) or Code;
+end;
+
+function TShlComRec_QueryContextMenu(Self: PContextMenu3_Interface; Menu: hMenu;
+ indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult; stdcall;
+type
+ TDllVersionInfo = record
+ cbSize: DWORD;
+ dwMajorVersion: DWORD;
+ dwMinorVersion: DWORD;
+ dwBuildNumber: DWORD;
+ dwPlatformID: DWORD;
+ end;
+
+ TDllGetVersionProc = function(var dv: TDllVersionInfo): HResult; stdcall;
+var
+ hShellInst: THandle;
+ bMF_OWNERDRAW: Boolean;
+ DllGetVersionProc: TDllGetVersionProc;
+ dvi: TDllVersionInfo;
+ ed: TEnumData;
+ hMap: THandle;
+ pipch: PHeaderIPC;
+begin
+ Result := 0;
+ if ((LOWORD(uFlags) and CMF_VERBSONLY) <> CMF_VERBSONLY) and
+ ((LOWORD(uFlags) and CMF_DEFAULTONLY) <> CMF_DEFAULTONLY) then
+ begin
+ bMF_OWNERDRAW := False;
+ // get the shell version
+ hShellInst := LoadLibrary('shell32.dll');
+ if hShellInst <> 0 then
+ begin
+ DllGetVersionProc := GetProcAddress(hShellInst, 'DllGetVersion');
+ if @DllGetVersionProc <> nil then
+ begin
+ dvi.cbSize := sizeof(TDllVersionInfo);
+ if DllGetVersionProc(dvi) >= 0 then
+ begin
+ // it's at least 4.00
+ bMF_OWNERDRAW := (dvi.dwMajorVersion > 4) or (dvi.dwMinorVersion >= 71);
+ end; // if
+ end; // if
+ FreeLibrary(hShellInst);
+ end; // if
+
+ // if we're using Vista (or later), then the ownerdraw code will be disabled, because the system draws the icons.
+ if VistaOrLater then
+ bMF_OWNERDRAW := False;
+
+ hMap := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, IPC_PACKET_SIZE,
+ IPC_PACKET_NAME);
+ If (hMap <> 0) and (GetLastError <> ERROR_ALREADY_EXISTS) then
+ begin
+ { map the memory to this address space }
+ pipch := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+ If pipch <> nil then
+ begin
+ { let the callback have instance vars }
+ ed.Self := Self^.ptrInstance;
+ // not used 'ere
+ ed.Self^.hRootMenu := Menu;
+ // store the first ID to offset with index for InvokeCommand()
+ Self^.ptrInstance^.idCmdFirst := idCmdFirst;
+ // store the starting index to offset
+ Result := idCmdFirst;
+ ed.bOwnerDrawSupported := bMF_OWNERDRAW;
+ ed.bShouldOwnerDraw := True;
+ ed.idCmdFirst := idCmdFirst;
+ ed.ipch := pipch;
+ { allocate a wait object so the ST can signal us, it can't be anon
+ since it has to used by OpenEvent() }
+ lstrcpya(@pipch^.SignalEventName, PChar(CreateUID()));
+ { create the wait wait-for-wait object }
+ ed.hWaitFor := CreateEvent(nil, False, False, pipch^.SignalEventName);
+ If ed.hWaitFor <> 0 then
+ begin
+ { enumerate all the top level windows to find all loaded MIRANDANAME
+ classes -- }
+ EnumWindows(@ProcessRequest, lParam(@ed));
+ { close the wait-for-reply object }
+ CloseHandle(ed.hWaitFor);
+ end;
+ { unmap the memory from this address space }
+ UnmapViewOfFile(pipch);
+ end; { if }
+ { close the mapping }
+ CloseHandle(hMap);
+ // use the MSDN recommended way, thou there ain't much difference
+ Result := MAKE_HRESULT(0, 0, (ed.idCmdFirst - Result) + 1);
+ end
+ else
+ begin
+ // the mapping file already exists, which is not good!
end;
-
- { this callback is triggered by the menu code and IPC is already taking place,
- just the transfer type+data needs to be setup }
- function ClearMRUIPC(
- pipch: PHeaderIPC; // IPC header info, already mapped
- hWorkThreadEvent: THandle; // event object being waited on on miranda thread
- hAckEvent: THandle; // ack event object that has been created
- psd: PMenuDrawInfo // command/draw info
- ): Integer; stdcall;
- begin
- Result := S_OK;
- ipcPrepareRequests(IPC_PACKET_SIZE, pipch, REQUEST_CLEARMRU);
- ipcSendRequest(hWorkThreadEvent, hAckEvent, pipch, 100) ;
- end; - - procedure RemoveCheckmarkSpace(hMenu: HMENU); - const - MIM_STYLE = $00000010; - MNS_CHECKORBMP = $4000000; - type - TMENUINFO = record - cbSize: DWORD; - fMask: DWORD; - dwStyle: DWORD; - cyMax: LongInt; - hbrBack: THandle; - dwContextHelpID: DWORD; - dwMenuData: Pointer; - end; - var - SetMenuInfo: function(hMenu: HMENU; var mi: TMenuInfo): Boolean; stdcall; - mi: TMENUINFO; - begin - if not VistaOrLater then Exit; - SetMenuInfo := GetProcAddress(GetModuleHandle('user32'), 'SetMenuInfo'); - if @SetMenuInfo = nil then Exit; - mi.cbSize := sizeof(mi); - mi.fMask := MIM_STYLE; - mi.dwStyle := MNS_CHECKORBMP; - SetMenuInfo(hMenu, mi); - end;
- - procedure BuildMenus(lParam: PEnumData); - {$define SHL_IDC} - {$define SHL_KEYS} - {$include shlc.inc} - {$undef SHL_KEYS} - {$undef SHL_IDC} - var - hBaseMenu: HMENU; - hGroupMenu: HMENU; - pg: PSlotIPC; - szProf: PChar; - mii: TMenuItemInfo; - j: TGroupNodeList; - p, q: PGroupNode; - Depth, Hash: Cardinal; - Token: PChar; - tk: TStrTokRec; - szBuf: PChar; - hDllHeap: THandle; - psd: PMenuDrawInfo; - c: Cardinal; - pp: ^TSlotProtoIconsArray; - begin - ZeroMemory(@mii, sizeof(mii)); - hDllHeap := lParam^.Self^.hDllHeap; - hBaseMenu := lParam^.Self^.hRootMenu; - // build an in memory tree of the groups - pg := lParam^.ipch^.GroupsBegin; - tk.szSet := ['\']; - tk.bSetTerminator := False; - j.First := nil; - j.Last := nil; - while pg <> nil do - begin - if (pg^.cbSize <> sizeof(TSlotIPC)) or (pg^.fType <> REQUEST_GROUPS) then Break; - Depth := 0; - p := j.First; // start at root again - // get the group - Integer(tk.szStr) := (Integer(pg) + sizeof(TSlotIPC)); - // find each word between \ and create sub groups if needed. - Token := StrTok(tk); - while Token <> nil do - begin - Hash := StrHash(Token); - // if the (sub)group doesn't exist, create it. - q := FindGroupNode(p, Hash, Depth); - if q = nil then - begin - q := AllocGroupNode(@j, p, Depth); - q^.Depth := Depth; - // this is the hash of this group node, but it can be anywhere - // i.e. Foo\Foo this is because each node has a different depth - // trouble is contacts don't come with depths! - q^.Hash := Hash; - // don't assume that pg^.hGroup's hash is valid for this token - // since it maybe Miranda\Blah\Blah and we have created the first node - // which maybe Miranda, thus giving the wrong hash - // since "Miranda" can be a group of it's own and a full path - q^.cchGroup := lstrlen(Token); - q^.szGroup := HeapAlloc(hDllHeap, 0, q^.cchGroup+1); - strcpy(q^.szGroup, Token); - q^.dwItems := 0; - end; - p := q; - Inc(Depth); - Token := StrTok(tk); - end; //while - pg := pg^.Next; - end; // while - // build the menus inserting into hGroupMenu which will be a submenu of - // the instance menu item. e.g. Miranda -> [Groups ->] contacts - hGroupMenu := CreatePopupMenu();
-
- // allocate MRU menu, this will be associated with the higher up menu
- // so doesn't need to be freed (unless theres no MRUs items attached)
- // This menu is per process but the handle is stored globally (like a stack)
- lParam^.Self^.hRecentMenu := CreatePopupMenu();
- lParam^.Self^.RecentCount := 0; - // create group menus only if they exist! - if lParam^.ipch^.GroupsBegin <> nil then - begin - BuildMenuGroupTree(j.First, lParam, hGroupMenu); - // add contacts that have a group somewhere - BuildContactTree(j.First, lParam); - end; - // - mii.cbSize := sizeof(TMenuItemInfo); - mii.fMask := MIIM_ID or MIIM_TYPE or MIIM_DATA; - // add all the contacts that have no group (which maybe all of them) - pg := lParam^.ipch^.ContactsBegin; - while pg <> nil do - begin - if (pg^.cbSize <> sizeof(TSlotIPC)) or (pg^.fType <> REQUEST_CONTACTS) then Break; - if pg^.hGroup = 0 then - begin - DecideMenuItemInfo(pg, nil, mii, lParam);
- BuildMRU(pg, mii, lParam); - InsertMenuItem(hGroupMenu, $FFFFFFFF, True, mii); - end; //if - pg := pg^.Next; - end; //while
-
- // insert MRU menu as a submenu of the contact menu only if
- // the MRU list has been created, the menu popup will be deleted by itself
- if lParam^.Self^.RecentCount > 0 then
- begin
-
- // insert seperator and 'clear list' menu
- mii.fType := MFT_SEPARATOR;
- mii.fMask := MIIM_TYPE;
- InsertMenuitem(lParam^.Self^.hRecentMenu, $FFFFFFFF, True, mii);
-
- // insert 'clear MRU' item and setup callback
- mii.fMask := MIIM_TYPE or MIIM_ID or MIIM_DATA;
- mii.wID := lParam^.idCmdFirst;
- Inc(lParam^.idCmdFirst);
- mii.fType := MFT_STRING;
- mii.dwTypeData := lParam^.ipch^.ClearEntries; // "Clear entries"
- //allocate menu substructure
- psd := HeapAlloc(hDllHeap, 0, sizeof(TMenuDrawInfo));
- psd^.fTypes := [dtCommand];
- psd^.MenuCommandCallback := @ClearMRUIPC;
- psd^.wID := mii.wID;
- // this is needed because there is a clear list command per each process.
- psd^.pid := lParam^.pid;
- mii.dwItemData := Integer(psd);
- InsertMenuitem(lParam^.Self^.hRecentMenu, $FFFFFFFF, True, mii);
-
- // insert MRU submenu into group menu (with) ownerdraw support as needed
- psd := HeapAlloc(hDllHeap, 0, sizeof(TMenuDrawInfo));
- psd^.szProfile := 'MRU';
- psd^.fTypes := [dtGroup];
- // the IPC string pointer wont be around forever, must make a copy
- psd^.cch := strlen(lParam^.ipch^.MRUMenuName);
- psd^.szText := HeapAlloc(hDllHeap, 0, psd^.cch+1);
- lstrcpyn(psd^.szText, lParam^.ipch^.MRUMenuName, sizeof(lParam^.ipch^.MRUMenuName)-1);
-
- mii.dwItemData := Integer(psd);
- if (lParam^.bOwnerDrawSupported) and (lParam^.bShouldOwnerDraw) then
- begin
- mii.fType := MFT_OWNERDRAW;
- Pointer(mii.dwTypeData) := psd;
- end else
- begin
- mii.dwTypeData := lParam^.ipch^.MRUMenuName; // 'Recent';
- end;
- mii.wID := lParam^.idCmdFirst;
- Inc(lParam^.idCmdFirst);
- mii.fMask := MIIM_TYPE or MIIM_SUBMENU or MIIM_DATA or MIIM_ID;
- mii.hSubMenu := lParam^.Self^.hRecentMenu;
- InsertMenuItem(hGroupMenu, 0, True, mii);
- end
- else
- begin
- // no items were attached to the MRU, delete the MRU menu
- DestroyMenu(lParam^.Self^.hRecentMenu);
- lParam^.Self^.hRecentMenu := 0;
- end; -
- // allocate display info/memory for "Miranda" string
- - mii.cbSize := sizeof(TMenuItemInfo); - mii.fMask := MIIM_ID or MIIM_DATA or MIIM_TYPE or MIIM_SUBMENU; - if VistaOrLater then - begin - mii.fMask := MIIM_ID or MIIM_DATA or MIIM_FTYPE or MIIM_SUBMENU or MIIM_STRING or MIIM_BITMAP; - end; - mii.hSubMenu := hGroupMenu; - - // by default, the menu will have space for icons and checkmarks (on Vista+) and we don't need this - RemoveCheckmarkSpace(hGroupMenu); -
- - psd := HeapAlloc(hDllHeap, 0, sizeof(TMenuDrawInfo)); - psd^.cch := strlen(lParam^.ipch^.MirandaName); - psd^.szText := HeapAlloc(hDllHeap, 0, psd^.cch+1); - lstrcpyn(psd^.szText, lParam^.ipch^.MirandaName, sizeof(lParam^.ipch^.MirandaName)-1); - // there may not be a profile name - pg := lParam^.ipch^.DataPtr; - psd^.szProfile := nil; - if ((pg <> nil) and (pg^.Status = STATUS_PROFILENAME)) then - begin - psd^.szProfile := HeapAlloc(hDllHeap, 0, pg^.cbStrSection); - strcpy(psd^.szProfile, PChar(Integer(pg) + sizeof(TSlotIPC))); - end; //if - // owner draw menus need ID's - mii.wID := lParam^.idCmdFirst; - Inc(lParam^.idCmdFirst); - psd^.fTypes := [dtEntry]; - psd^.wID := mii.wID; - psd^.hContact := 0; - // get Miranda's icon or bitmap - c := lParam^.Self^.protoIconsCount; - pp := lParam^.Self^.protoIcons; - while c > 0 do - begin - dec(c); - if (pp[c].pid = lParam^.pid) and (pp[c].hProto = 0) then - begin - // either of these can be 0 - psd^.hStatusIcon := pp[c].hIcons[0]; - mii.hBmpItem := pp[c].hBitmaps[0]; - break; - end; //if - end; //while - mii.dwItemData := Integer(psd); - if ((lParam^.bOwnerDrawSupported) and (lParam^.bShouldOwnerDraw)) then - begin - mii.fType := MFT_OWNERDRAW; - Pointer(mii.dwTypeData) := psd; - end else begin - mii.fType := MFT_STRING; - mii.dwTypeData := lParam^.ipch^.MirandaName; - mii.cch := sizeof(lParam^.ipch^.MirandaName)-1; - end; - // add it all - InsertMenuItem(hBaseMenu, 0, True, mii); - // free the group tree - FreeGroupTreeAndEmptyGroups(hGroupMenu, nil, j.First); - end; - - procedure BuildSkinIcons(lParam: PEnumData); - var - pct: PSlotIPC; - p, d: PSlotProtoIcons; - Self: PShlComRec; - j: Cardinal; - imageFactory: PImageFactory_Interface; - begin - pct := lParam^.ipch^.NewIconsBegin; - self := lParam^.Self; - while (pct <> nil) do - begin - if (pct^.cbSize <> sizeof(TSlotIPC)) or (pct^.fType <> REQUEST_NEWICONS) then Break; - Integer(p) := Integer(pct) + sizeof(TSlotIPC); - ReAllocMem(self^.protoIcons, (self^.protoIconsCount+1)*sizeof(TSlotProtoIcons)); - d := @self^.protoIcons[self^.protoIconsCount]; - CopyMemory(d,p,sizeof(TSlotProtoIcons)); - - { - If using Vista (or later), clone all the icons into bitmaps and keep these around, - if using anything older, just use the default code, the bitmaps (and or icons) will be freed - with the shell object. - } - - imageFactory := nil; - - for j := 0 to 9 do - begin - if imageFactory = nil then imageFactory := ARGB_GetWorker(); - if VistaOrLater then - begin - d^.hBitmaps[j] := ARGB_BitmapFromIcon(imageFactory, self^.hMemDC, p^.hIcons[j] ); - d^.hIcons[j] := 0; - end else - begin - d^.hBitmaps[j] := 0; - d^.hIcons[j] := CopyIcon(p^.hIcons[j]); - end; - end; - - if imageFactory <> nil then - begin - imageFactory^.ptrVTable^.Release(imageFactory); - imageFactory := nil; - end; - - inc(self^.protoIconsCount); - pct := pct^.Next; - end; - end; - - function ProcessRequest(hwnd: HWND; lParam: PEnumData): BOOL; stdcall; - var - pid: Integer; - hMirandaWorkEvent: THandle; - replyBits: Integer; - hScreenDC: THandle; - szBuf: array[0..MAX_PATH] of Char; - begin - Result := True; - pid := 0; - GetWindowThreadProcessId(hwnd, @pid); - If pid <> 0 then - begin - // old system would get a window's pid and the module handle that created it - // and try to OpenEvent() a event object name to it (prefixed with a string) - // this was fine for most Oses (not the best way) but now actually compares - // the class string (a bit slower) but should get rid of those bugs finally. - hMirandaWorkEvent := OpenEvent(EVENT_ALL_ACCESS, False, PChar(CreateProcessUID(pid))); - if (hMirandaWorkEvent <> 0) then - begin - GetClassName(hwnd, szBuf, sizeof(szBuf)); - if lstrcmp(szBuf, MIRANDANAME) <> 0 then - begin - // opened but not valid. - CloseHandle(hMirandaWorkEvent); Exit; - end; //if - end; //if
- { If the event object exists, then a shlext.dll running in the instance must of created it. } - If hMirandaWorkEvent <> 0 then - begin - { prep the request } - ipcPrepareRequests(IPC_PACKET_SIZE, lParam^.ipch, REQUEST_ICONS or REQUEST_GROUPS or REQUEST_CONTACTS or REQUEST_NEWICONS); - // slots will be in the order of icon data, groups then contacts, the first - // slot will contain the profile name - replyBits := ipcSendRequest(hMirandaWorkEvent, lParam^.hWaitFor, lParam^.ipch, 1000); - { replyBits will be REPLY_FAIL if the wait timed out, or it'll be the request - bits as sent or a series of *_NOTIMPL bits where the request bit were, if there are no - contacts to speak of, then don't bother showing this instance of Miranda } - if (replyBits <> REPLY_FAIL) and (lParam^.ipch^.ContactsBegin <> nil) then - begin - // load the address again, the server side will always overwrite it - lParam^.ipch^.pClientBaseAddress := lParam^.ipch; - // fixup all the pointers to be relative to the memory map - // the base pointer of the client side version of the mapped file - ipcFixupAddresses(False, lParam^.ipch); - // store the PID used to create the work event object - // that got replied to -- this is needed since each contact - // on the final menu maybe on a different instance and another OpenEvent() will be needed. - lParam^.pid := pid; - // check out the user options from the server - lParam^.bShouldOwnerDraw := (lParam^.ipch^.dwFlags and HIPC_NOICONS) = 0; - // process the icons - BuildSkinIcons(lParam); - // process other replies - BuildMenus(lParam); - end; - { close the work object } - CloseHandle(hMirandaWorkEvent); - end; //if - end; //if - end; - - function TShlComRec_QueryInterface(Self: PCommon_Interface; - const IID: TIID; var Obj): HResult; stdcall; - begin - Pointer(Obj) := nil; - { IShellExtInit is given when the TShlRec is created } - if IsEqualIID(IID, IID_IContextMenu) - or IsEqualIID(IID, IID_IContextMenu2) - or IsEqualIID(IID, IID_IContextMenu3) then - begin - with Self^.ptrInstance^ do - begin - Pointer(Obj) := @ContextMenu3_Interface; - Inc(RefCount); - end; {with} - Result := S_OK; - end else begin - // under XP, it may ask for IShellExtInit again, this fixes the -double- click to see menus issue - // which was really just the object not being created - if IsEqualIID(IID, IID_IShellExtInit) then - begin - with Self^.ptrInstance^ do - begin - Pointer(Obj) := @ShellExtInit_Interface; - Inc(RefCount); - end; //if - Result := S_OK; - end else begin - Result := CLASS_E_CLASSNOTAVAILABLE; - end; //if - end; //if - end; - - function TShlComRec_AddRef(Self: PCommon_Interface): LongInt; stdcall; - begin - with Self^.ptrInstance^ do - begin - Inc(RefCount); - Result := RefCount; - end; {with} - end; - - function TShlComRec_Release(Self: PCommon_Interface): LongInt; stdcall; - var - j, c: Cardinal; - begin - with Self^.ptrInstance^ do - begin - Dec(RefCount); - Result := RefCount; - If RefCount = 0 then - begin - // time to go byebye. - with Self^.ptrInstance^ do + end
+ else
+ begin
+ // same as giving a SEVERITY_SUCCESS, FACILITY_NULL, since that
+ // just clears the higher bits, which is done anyway
+ Result := MAKE_HRESULT(0, 0, 1);
+ end; // if
+end;
+
+function TShlComRec_GetCommandString(Self: PContextMenu3_Interface; idCmd, uType: UINT;
+ pwReserved: PUINT; pszName: PChar; cchMax: UINT): HResult; stdcall;
+begin
+ Result := E_NOTIMPL;
+end;
+
+function ipcGetFiles(pipch: PHeaderIPC; pDataObject: PDataObject_Interface;
+ const hContact: THandle): Integer;
+type
+ TDragQueryFile = function(hDrop: THandle; fileIndex: Integer; FileName: PChar;
+ cbSize: Integer): Integer; stdcall;
+var
+ fet: TFormatEtc;
+ stgm: TStgMedium;
+ pct: PSlotIPC;
+ iFile: Cardinal;
+ iFileMax: Cardinal;
+ hShell: THandle;
+ DragQueryFile: TDragQueryFile;
+ cbSize: Integer;
+ hDrop: THandle;
+begin
+ Result := E_INVALIDARG;
+ hShell := LoadLibrary('shell32.dll');
+ if hShell <> 0 then
+ begin
+ DragQueryFile := GetProcAddress(hShell, 'DragQueryFileA');
+ if @DragQueryFile <> nil then
+ begin
+ fet.cfFormat := CF_HDROP;
+ fet.ptd := nil;
+ fet.dwAspect := DVASPECT_CONTENT;
+ fet.lindex := -1;
+ fet.tymed := TYMED_HGLOBAL;
+ Result := pDataObject^.ptrVTable^.GetData(pDataObject, fet, stgm);
+ if Result = S_OK then
+ begin
+ // FIX, actually lock the global object and get a pointer
+ Pointer(hDrop) := GlobalLock(stgm.hGlobal);
+ if hDrop <> 0 then
+ begin
+ // get the maximum number of files
+ iFileMax := DragQueryFile(stgm.hGlobal, $FFFFFFFF, nil, 0);
+ iFile := 0;
+ while iFile < iFileMax do
+ begin
+ // get the size of the file path
+ cbSize := DragQueryFile(stgm.hGlobal, iFile, nil, 0);
+ // get the buffer
+ pct := ipcAlloc(pipch, cbSize + 1); // including null term
+ // allocated?
+ if pct = nil then
+ break;
+ // store the hContact
+ pct^.hContact := hContact;
+ // copy it to the buffer
+ DragQueryFile(stgm.hGlobal, iFile, PChar(Integer(pct) + sizeof(TSlotIPC)),
+ pct^.cbStrSection);
+ // next file
+ inc(iFile);
+ end; // while
+ // store the number of files
+ pipch^.Slots := iFile;
+ GlobalUnlock(stgm.hGlobal);
+ end; // if hDrop check
+ // release the mediumn the lock may of failed
+ ReleaseStgMedium(stgm);
+ end; // if
+ end; // if
+ // free the dll
+ FreeLibrary(hShell);
+ end; // if
+end;
+
+function RequestTransfer(Self: PShlComRec; idxCmd: Integer): Integer;
+var
+ hMap: THandle;
+ pipch: PHeaderIPC;
+ mii: TMenuItemInfo;
+ hTransfer: THandle;
+ psd: PMenuDrawInfo;
+ hReply: THandle;
+ replyBits: Integer;
+begin
+ Result := E_INVALIDARG;
+ // get the contact information
+ mii.cbSize := sizeof(TMenuItemInfo);
+ mii.fMask := MIIM_ID or MIIM_DATA;
+ if GetMenuItemInfo(Self^.hRootMenu, Self^.idCmdFirst + idxCmd, False, mii) then
+ begin
+ // get the pointer
+ int_ptr(psd) := mii.dwItemData;
+ // the ID stored in the item pointer and the ID for the menu must match
+ if (psd = nil) or (psd^.wID <> mii.wID) then
+ begin
+ // MessageBox(0,'ptr assocated with menu is NULL','',MB_OK);
+ Exit;
+ end; // if
+ end
+ else
+ begin
+ // MessageBox(0,'GetMenuItemInfo failed?','',MB_OK);
+ // couldn't get the info, can't start the transfer
+ Result := E_INVALIDARG;
+ Exit;
+ end; // if
+ // is there an IDataObject instance?
+ if Self^.pDataObject <> nil then
+ begin
+ // OpenEvent() the work object to see if the instance is still around
+ hTransfer := OpenEvent(EVENT_ALL_ACCESS, False, PChar(CreateProcessUID(psd^.pid)));
+ if hTransfer <> 0 then
+ begin
+ // map the ipc file again
+ hMap := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, IPC_PACKET_SIZE,
+ IPC_PACKET_NAME);
+ if (hMap <> 0) and (GetLastError <> ERROR_ALREADY_EXISTS) then
+ begin
+ // map it to process
+ pipch := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+ if pipch <> nil then
+ begin
+ // create the name of the object to be signalled by the ST
+ lstrcpya(pipch^.SignalEventName, PChar(CreateUID()));
+ // create it
+ hReply := CreateEvent(nil, False, False, pipch^.SignalEventName);
+ if hReply <> 0 then
+ begin
+ if dtCommand in psd^.fTypes then
+ begin
+ if Assigned(psd^.MenuCommandCallback) then
+ Result := psd^.MenuCommandCallback(pipch, hTransfer, hReply, psd);
+ end
+ else
+ begin
+
+ // prepare the buffer
+ ipcPrepareRequests(IPC_PACKET_SIZE, pipch, REQUEST_XFRFILES);
+ // get all the files into the packet
+ if ipcGetFiles(pipch, Self^.pDataObject, psd^.hContact) = S_OK then
+ begin
+ // need to wait for the ST to open the mapping object
+ // since if we close it before it's opened it the data it
+ // has will be undefined
+ replyBits := ipcSendRequest(hTransfer, hReply, pipch, 200);
+ if replyBits <> REPLY_FAIL then
begin
- // Note MRU menu is associated with a window (indirectly) so windows will free it. - // free icons! - if protoIcons <> nil then - begin - c := protoIconsCount; - while c > 0 do - begin - dec(c); - for j := 0 to 9 do - begin - with protoIcons[c] do - begin - if hIcons[j] <> 0 then DestroyIcon(hIcons[j]); - if hBitmaps[j] <> 0 then DeleteObject(hBitmaps[j]); - end; - end; - end; - FreeMem(protoIcons); protoIcons := nil; - end; //if - // free IDataObject reference if pointer exists - if pDataObject <> nil then - begin - pDataObject^.ptrvTable^.Release(pDataObject); - end; //if - pDataObject := nil; - // free the heap and any memory allocated on it - HeapDestroy(hDllHeap); - // destroy the DC - if hMemDC <> 0 then DeleteDC(hMemDC); - end; //with - // free the instance (class record) created - Dispose(Self^.ptrInstance); - Dec(dllpublic.ObjectCount); - end; {if} - end; {with} - end; - - function TShlComRec_Initialise(Self: PContextMenu3_Interface; - pidLFolder: Pointer; DObj: PDataObject_Interface; hKeyProdID: HKEY): HResult; stdcall; - begin - // DObj is a pointer to an instance of IDataObject which is a pointer itself - // it contains a pointer to a function table containing the function pointer - // address of GetData() - the instance data has to be passed explicitly since - // all compiler magic has gone. - with Self^.ptrInstance^ do - begin - if DObj <> nil then - begin - Result := S_OK; - // if an instance already exists, free it. - if pDataObject <> nil then pDataObject^.ptrVTable^.Release(pDataObject); - // store the new one and AddRef() it - pDataObject := DObj; - pDataObject^.ptrVTable^.AddRef(pDataObject); - end else begin - Result := E_INVALIDARG; - end; //if - end; //if - end; - - function MAKE_HRESULT(Severity, Facility, Code: Integer): HResult; - {$ifdef FPC} - inline; - {$endif} - begin - Result := (Severity shl 31) or (Facility shl 16) or Code; - end; - - function TShlComRec_QueryContextMenu(Self: PContextMenu3_Interface; - Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult; stdcall; - type - TDllVersionInfo = record - cbSize: DWORD; - dwMajorVersion: DWORD; - dwMinorVersion: DWORD; - dwBuildNumber: DWORD; - dwPlatformID: DWORD; - end; - TDllGetVersionProc = function(var dv: TDllVersionInfo): HResult; stdcall; - var - hShellInst: THandle; - bMF_OWNERDRAW: Boolean; - DllGetVersionProc: TDllGetVersionProc; - dvi: TDllVersionInfo; - ed: TEnumData; - hMap: THandle; - pipch: PHeaderIPC; - begin - Result := 0; - if ((LOWORD(uFlags) and CMF_VERBSONLY) <> CMF_VERBSONLY) and ((LOWORD(uFlags) and CMF_DEFAULTONLY) <> CMF_DEFAULTONLY) then - begin - bMF_OWNERDRAW := False; - // get the shell version - hShellInst := LoadLibrary('shell32.dll'); - if hShellInst <> 0 then - begin - DllGetVersionProc := GetProcAddress(hShellInst, 'DllGetVersion'); - if @DllGetVersionProc <> nil then - begin - dvi.cbSize := sizeof(TDllVersionInfo); - if DllGetVersionProc(dvi) >= 0 then - begin - // it's at least 4.00 - bMF_OWNERDRAW := (dvi.dwMajorVersion > 4) or (dvi.dwMinorVersion >= 71); - end; //if - end; //if - FreeLibrary(hShellInst); - end; //if - - // if we're using Vista (or later), then the ownerdraw code will be disabled, because the system draws the icons. - if VistaOrLater then bMF_OWNERDRAW := False; - - hMap := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, IPC_PACKET_SIZE, IPC_PACKET_NAME); - If (hMap <> 0) and (GetLastError <> ERROR_ALREADY_EXISTS) then - begin - { map the memory to this address space } - pipch := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); - If pipch <> nil then - begin - { let the callback have instance vars } - ed.Self := Self^.ptrInstance; - // not used 'ere - ed.Self^.hRootMenu := Menu; - // store the first ID to offset with index for InvokeCommand() - Self^.ptrInstance^.idCmdFirst := idCmdFirst; - // store the starting index to offset - Result := idCmdFirst; - ed.bOwnerDrawSupported := bMF_OWNERDRAW; - ed.bShouldOwnerDraw := True; - ed.idCmdFirst := idCmdFirst; - ed.ipch := pipch; - { allocate a wait object so the ST can signal us, it can't be anon - since it has to used by OpenEvent() } - strcpy(@pipch^.SignalEventName, PChar(CreateUID())); - { create the wait wait-for-wait object } - ed.hWaitFor := CreateEvent(nil, False, False, pipch^.SignalEventName); - If ed.hWaitFor <> 0 then - begin - { enumerate all the top level windows to find all loaded MIRANDANAME - classes -- } - EnumWindows(@ProcessRequest, lParam(@ed)); - { close the wait-for-reply object } - CloseHandle(ed.hWaitFor); - end; - { unmap the memory from this address space } - UnmapViewOfFile(pipch); - end; {if} - { close the mapping } - CloseHandle(hMap); - // use the MSDN recommended way, thou there ain't much difference - Result := MAKE_HRESULT(0, 0, (ed.idCmdFirst - Result) + 1); - end else begin - // the mapping file already exists, which is not good! - end; - end else begin - // same as giving a SEVERITY_SUCCESS, FACILITY_NULL, since that - // just clears the higher bits, which is done anyway - Result := MAKE_HRESULT(0, 0, 1); - end; //if - end; - - function TShlComRec_GetCommandString(Self: PContextMenu3_Interface; - idCmd, uType: UINT; pwReserved: PUINT; pszName: PChar; cchMax: UINT): HResult; stdcall; - begin - Result := E_NOTIMPL; - end; - - function ipcGetFiles(pipch: PHeaderIPC; pDataObject: PDataObject_Interface; const hContact: THandle): Integer; - type - TDragQueryFile = function(hDrop: THandle; fileIndex: Integer; FileName: PChar; cbSize: Integer): Integer; stdcall; - var - fet: TFormatEtc; - stgm: TStgMedium; - pct: PSlotIPC; - iFile: Cardinal; - iFileMax: Cardinal; - hShell: THandle; - DragQueryFile: TDragQueryFile; - cbSize: Integer; - hDrop: THandle; - begin - Result := E_INVALIDARG; - hShell := LoadLibrary('shell32.dll'); - if hShell <> 0 then - begin - DragQueryFile := GetProcAddress(hShell, 'DragQueryFileA'); - if @DragQueryFile <> nil then - begin - fet.cfFormat := CF_HDROP; - fet.ptd := nil; - fet.dwAspect := DVASPECT_CONTENT; - fet.lindex := -1; - fet.tymed := TYMED_HGLOBAL; - Result := pDataObject^.ptrVTable^.GetData(pDataObject, fet, stgm); - if Result = S_OK then - begin - // FIX, actually lock the global object and get a pointer - Pointer(hDrop) := GlobalLock(stgm.hGlobal); - if hDrop <> 0 then - begin - // get the maximum number of files - iFileMax := DragQueryFile(stgm.hGlobal, $FFFFFFFF, nil, 0); - iFile := 0; - while iFile < iFileMax do - begin - // get the size of the file path - cbSize := DragQueryFile(stgm.hGlobal, iFile, nil, 0); - // get the buffer - pct := ipcAlloc(pipch, cbSize + 1); // including null term - // allocated? - if pct = nil then Break; - // store the hContact - pct^.hContact := hContact; - // copy it to the buffer - DragQueryFile(stgm.hGlobal, iFile, PChar(Integer(pct)+sizeof(TSlotIPC)), pct^.cbStrSection); - // next file - Inc(iFile); - end; //while - // store the number of files - pipch^.Slots := iFile; - GlobalUnlock(stgm.hGlobal); - end; //if hDrop check - // release the mediumn the lock may of failed - ReleaseStgMedium(stgm); - end; //if - end; //if - // free the dll - FreeLibrary(hShell); - end; //if - end; - - function RequestTransfer(Self: PShlComRec; idxCmd: Integer): Integer; - var - hMap: THandle; - pipch: PHeaderIPC; - mii: TMenuItemInfo; - hTransfer: THandle; - psd: PMenuDrawInfo; - hReply: THandle; - replyBits: Integer; + // they got the files!
+ Result := S_OK;
+ end; // if
+ end;
+
+ end;
+ // close the work object name
+ CloseHandle(hReply);
+ end; // if
+ // unmap it from this process
+ UnmapViewOfFile(pipch);
+ end; // if
+ // close the map
+ CloseHandle(hMap);
+ end; // if
+ // close the handle to the ST object name
+ CloseHandle(hTransfer);
+ end; // if
+ end // if;
+end;
+
+function TShlComRec_InvokeCommand(Self: PContextMenu3_Interface;
+ var lpici: TCMInvokeCommandInfo): HResult; stdcall;
+begin
+ Result := RequestTransfer(Self^.ptrInstance, LOWORD(Integer(lpici.lpVerb)));
+end;
+
+function TShlComRec_HandleMenuMsgs(Self: PContextMenu3_Interface; uMsg: UINT; wParam: wParam;
+ lParam: lParam; pResult: PLResult): HResult;
+const
+ WM_DRAWITEM = $002B;
+ WM_MEASUREITEM = $002C;
+var
+ dwi: PDrawItemStruct;
+ msi: PMeasureItemStruct;
+ psd: PMenuDrawInfo;
+ ncm: TNonClientMetrics;
+ hOldFont: THandle;
+ hFont: THandle;
+ tS: TSize;
+ dx: Integer;
+ hBr: HBRUSH;
+ icorc: TRect;
+ hMemDC: HDC;
+begin
+ pResult^ := Integer(True);
+ if (uMsg = WM_DRAWITEM) and (wParam = 0) then
+ begin
+ // either a main sub menu, a group menu or a contact
+ dwi := PDrawItemStruct(lParam);
+ int_ptr(psd) := dwi^.itemData;
+ // don't fill
+ SetBkMode(dwi^.HDC, TRANSPARENT);
+ // where to draw the icon?
+ icorc.Left := 0;
+ // center it
+ with dwi^ do
+ icorc.Top := rcItem.Top + ((rcItem.Bottom - rcItem.Top) div 2) - (16 div 2);
+ icorc.Right := icorc.Left + 16;
+ icorc.Bottom := icorc.Top + 16;
+ // draw for groups
+ if (dtGroup in psd^.fTypes) or (dtEntry in psd^.fTypes) then
+ begin
+ hBr := GetSysColorBrush(COLOR_MENU);
+ FillRect(dwi^.HDC, dwi^.rcItem, hBr);
+ DeleteObject(hBr);
+ //
+ if (ODS_SELECTED and dwi^.itemState = ODS_SELECTED) then
+ begin
+ // only do this for entry menu types otherwise a black mask
+ // is drawn under groups
+ hBr := GetSysColorBrush(COLOR_HIGHLIGHT);
+ FillRect(dwi^.HDC, dwi^.rcItem, hBr);
+ DeleteObject(hBr);
+ SetTextColor(dwi^.HDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ end; // if
+ // draw icon
+ with dwi^, icorc do
+ begin
+ if (ODS_SELECTED and dwi^.itemState) = ODS_SELECTED then
+ begin
+ hBr := GetSysColorBrush(COLOR_HIGHLIGHT);
+ end
+ else
+ begin
+ hBr := GetSysColorBrush(COLOR_MENU);
+ end; // if
+ DrawIconEx(HDC, Left + 1, Top, psd^.hStatusIcon, 16, 16, // width, height
+ 0, // step
+ hBr, // brush
+ DI_NORMAL);
+ DeleteObject(hBr);
+ end; // with
+ // draw the text
+ with dwi^ do
+ begin
+ inc(rcItem.Left, ((rcItem.Bottom - rcItem.Top) - 2));
+ DrawText(HDC, psd^.szText, psd^.cch, rcItem, DT_NOCLIP or DT_NOPREFIX or
+ DT_SINGLELINE or DT_VCENTER);
+ // draw the name of the database text if it's there
+ if psd^.szProfile <> nil then
+ begin
+ GetTextExtentPoint32(dwi^.HDC, psd^.szText, psd^.cch, tS);
+ inc(rcItem.Left, tS.cx + 8);
+ SetTextColor(HDC, GetSysColor(COLOR_GRAYTEXT));
+ DrawText(HDC, psd^.szProfile, lstrlena(psd^.szProfile), rcItem,
+ DT_NOCLIP or DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER);
+ end; // if
+ end; // with
+ end
+ else
+ begin
+ // it's a contact!
+ hBr := GetSysColorBrush(COLOR_MENU);
+ FillRect(dwi^.HDC, dwi^.rcItem, hBr);
+ DeleteObject(hBr);
+ if ODS_SELECTED and dwi^.itemState = ODS_SELECTED then
+ begin
+ hBr := GetSysColorBrush(COLOR_HIGHLIGHT);
+ FillRect(dwi^.HDC, dwi^.rcItem, hBr);
+ DeleteObject(hBr);
+ SetTextColor(dwi^.HDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ end;
+ // draw icon
+ with dwi^, icorc do
+ begin
+ if (ODS_SELECTED and dwi^.itemState) = ODS_SELECTED then
+ begin
+ hBr := GetSysColorBrush(COLOR_HIGHLIGHT);
+ end
+ else
+ begin
+ hBr := GetSysColorBrush(COLOR_MENU);
+ end; // if
+ DrawIconEx(HDC, Left + 2, Top, psd^.hStatusIcon, 16, 16, // width, height
+ 0, // step
+ hBr, // brush
+ DI_NORMAL);
+ DeleteObject(hBr);
+ end; // with
+ // draw the text
+ with dwi^ do
+ begin
+ inc(rcItem.Left, (rcItem.Bottom - rcItem.Top) + 1);
+ DrawText(HDC, psd^.szText, psd^.cch, rcItem, DT_NOCLIP or DT_NOPREFIX or
+ DT_SINGLELINE or DT_VCENTER);
+ end; // with
+ end; // if
+ end
+ else if (uMsg = WM_MEASUREITEM) then
+ begin
+ // don't check if it's really a menu
+ msi := PMeasureItemStruct(lParam);
+ int_ptr(psd) := msi^.itemData;
+ ncm.cbSize := sizeof(TNonClientMetrics);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @ncm, 0);
+ // create the font used in menus, this font should be cached somewhere really
+{$IFDEF FPC}
+ hFont := CreateFontIndirect(@ncm.lfMenuFont);
+{$ELSE}
+ hFont := CreateFontIndirect(ncm.lfMenuFont);
+{$ENDIF}
+ hMemDC := Self^.ptrInstance^.hMemDC;
+ // select in the font
+ hOldFont := SelectObject(hMemDC, hFont);
+ // default to an icon
+ dx := 16;
+ // get the size 'n' account for the icon
+ GetTextExtentPoint32(hMemDC, psd^.szText, psd^.cch, tS);
+ inc(dx, tS.cx);
+ // main menu item?
+ if psd^.szProfile <> nil then
+ begin
+ GetTextExtentPoint32(hMemDC, psd^.szProfile, lstrlena(psd^.szProfile), tS);
+ inc(dx, tS.cx);
+ end;
+ // store it
+ msi^.itemWidth := dx + Integer(ncm.iMenuWidth);
+ msi^.itemHeight := Integer(ncm.iMenuHeight) + 2;
+ if tS.cy > msi^.itemHeight then
+ inc(msi^.itemHeight, tS.cy - msi^.itemHeight);
+ // clean up
+ SelectObject(hMemDC, hOldFont);
+ DeleteObject(hFont);
+ end;
+ Result := S_OK;
+end;
+
+function TShlComRec_HandleMenuMsg(Self: PContextMenu3_Interface; uMsg: UINT; wParam: wParam;
+ lParam: lParam): HResult; stdcall;
+var
+ Dummy: HResult;
+begin
+ Result := TShlComRec_HandleMenuMsgs(Self, uMsg, wParam, lParam, @Dummy);
+end;
+
+function TShlComRec_HandleMenuMsg2(Self: PContextMenu3_Interface; uMsg: UINT; wParam: wParam;
+ lParam: lParam; PLResult: Pointer { ^LResult } ): HResult; stdcall;
+var
+ Dummy: HResult;
+begin
+ // this will be null if a return value isn't needed.
+ if PLResult = nil then
+ PLResult := @Dummy;
+ Result := TShlComRec_HandleMenuMsgs(Self, uMsg, wParam, lParam, PLResult);
+end;
+
+function TShlComRec_Create: PShlComRec;
+var
+ DC: HDC;
+begin
+ New(Result);
+ { build all the function tables for interfaces }
+ with Result^.ShellExtInit_Interface do
+ begin
+ { this is only owned by us... }
+ ptrVTable := @vTable;
+ { IUnknown }
+ vTable.QueryInterface := @TShlComRec_QueryInterface;
+ vTable.AddRef := @TShlComRec_AddRef;
+ vTable.Release := @TShlComRec_Release;
+ { IShellExtInit }
+ vTable.Initialise := @TShlComRec_Initialise;
+ { instance of a TShlComRec }
+ ptrInstance := Result;
+ end;
+ with Result^.ContextMenu3_Interface do
+ begin
+ ptrVTable := @vTable;
+ { IUnknown }
+ vTable.QueryInterface := @TShlComRec_QueryInterface;
+ vTable.AddRef := @TShlComRec_AddRef;
+ vTable.Release := @TShlComRec_Release;
+ { IContextMenu }
+ vTable.QueryContextMenu := @TShlComRec_QueryContextMenu;
+ vTable.InvokeCommand := @TShlComRec_InvokeCommand;
+ vTable.GetCommandString := @TShlComRec_GetCommandString;
+ { IContextMenu2 }
+ vTable.HandleMenuMsg := @TShlComRec_HandleMenuMsg;
+ { IContextMenu3 }
+ vTable.HandleMenuMsg2 := @TShlComRec_HandleMenuMsg2;
+ { instance data }
+ ptrInstance := Result;
+ end;
+ { initalise variables }
+ Result^.RefCount := 1;
+ Result^.hDllHeap := HeapCreate(0, 0, 0);
+ Result^.hRootMenu := 0;
+ Result^.hRecentMenu := 0;
+ Result^.RecentCount := 0;
+ Result^.idCmdFirst := 0;
+ Result^.pDataObject := nil;
+ Result^.ProtoIcons := nil;
+ Result^.ProtoIconsCount := 0;
+ // create an inmemory DC
+ DC := GetDC(0);
+ Result^.hMemDC := CreateCompatibleDC(DC);
+ ReleaseDC(0, DC);
+ { keep count on the number of objects }
+ inc(dllpublic.ObjectCount);
+end;
+
+{ IClassFactory }
+
+type
+
+ PVTable_IClassFactory = ^TVTable_IClassFactory;
+
+ TVTable_IClassFactory = record
+ { IUnknown }
+ QueryInterface: Pointer;
+ AddRef: Pointer;
+ Release: Pointer;
+ { IClassFactory }
+ CreateInstance: Pointer;
+ LockServer: Pointer;
+ end;
+
+ PClassFactoryRec = ^TClassFactoryRec;
+
+ TClassFactoryRec = record
+ ptrVTable: PVTable_IClassFactory;
+ vTable: TVTable_IClassFactory;
+ { fields }
+ RefCount: LongInt;
+ end;
+
+function TClassFactoryRec_QueryInterface(Self: PClassFactoryRec; const IID: TIID; var Obj)
+ : HResult; stdcall;
+begin
+ Pointer(Obj) := nil;
+ Result := E_NOTIMPL;
+end;
+
+function TClassFactoryRec_AddRef(Self: PClassFactoryRec): LongInt; stdcall;
+begin
+ inc(Self^.RefCount);
+ Result := Self^.RefCount;
+end;
+
+function TClassFactoryRec_Release(Self: PClassFactoryRec): LongInt; stdcall;
+begin
+ dec(Self^.RefCount);
+ Result := Self^.RefCount;
+ if Result = 0 then
+ begin
+ Dispose(Self);
+ dec(dllpublic.FactoryCount);
+ end; { if }
+end;
+
+function TClassFactoryRec_CreateInstance(Self: PClassFactoryRec; unkOuter: Pointer;
+ const IID: TIID; var Obj): HResult; stdcall;
+var
+ ShlComRec: PShlComRec;
+begin
+ Pointer(Obj) := nil;
+ Result := CLASS_E_NOAGGREGATION;
+ if unkOuter = nil then
+ begin
+ { Before Vista, the system queried for a IShell interface then queried for a context menu, Vista now
+ queries for a context menu (or a shell menu) then QI()'s the other interface }
+ if IsEqualIID(IID, IID_IContextMenu) then
+ begin
+ Result := S_OK;
+ ShlComRec := TShlComRec_Create;
+ Pointer(Obj) := @ShlComRec^.ContextMenu3_Interface;
+ end;
+ if IsEqualIID(IID, IID_IShellExtInit) then
+ begin
+ Result := S_OK;
+ ShlComRec := TShlComRec_Create;
+ Pointer(Obj) := @ShlComRec^.ShellExtInit_Interface;
+ end; // if
+ end; // if
+end;
+
+function TClassFactoryRec_LockServer(Self: PClassFactoryRec; fLock: BOOL): HResult; stdcall;
+begin
+ Result := E_NOTIMPL;
+end;
+
+function TClassFactoryRec_Create: PClassFactoryRec;
+begin
+ New(Result);
+ Result^.ptrVTable := @Result^.vTable;
+ { IUnknown }
+ Result^.vTable.QueryInterface := @TClassFactoryRec_QueryInterface;
+ Result^.vTable.AddRef := @TClassFactoryRec_AddRef;
+ Result^.vTable.Release := @TClassFactoryRec_Release;
+ { IClassFactory }
+ Result^.vTable.CreateInstance := @TClassFactoryRec_CreateInstance;
+ Result^.vTable.LockServer := @TClassFactoryRec_LockServer;
+ { inital the variables }
+ Result^.RefCount := 1;
+ { count the number of factories }
+ inc(dllpublic.FactoryCount);
+end;
+
+//
+// IPC part
+//
+
+type
+ PFileList = ^TFileList;
+ TFileList = array [0 .. 0] of PChar;
+ PAddArgList = ^TAddArgList;
+
+ TAddArgList = record
+ szFile: PChar; // file being processed
+ cch: Cardinal; // it's length (with space for NULL char)
+ count: Cardinal; // number we have so far
+ files: PFileList;
+ hContact: THandle;
+ hEvent: THandle;
+ end;
+
+function AddToList(var args: TAddArgList): LongBool;
+var
+ attr: Cardinal;
+ p: Pointer;
+ hFind: THandle;
+ fd: TWIN32FINDDATA;
+ szBuf: array [0 .. MAX_PATH] of Char;
+ szThis: PChar;
+ cchThis: Cardinal;
+begin
+ Result := False;
+ attr := GetFileAttributes(args.szFile);
+ if (attr <> $FFFFFFFF) and ((attr and FILE_ATTRIBUTE_HIDDEN) = 0) then
+ begin
+ if args.count mod 10 = 5 then
+ begin
+ if CallService(MS_SYSTEM_TERMINATED, 0, 0) <> 0 then
+ begin
+ Result := True;
+ Exit;
+ end; // if
+ end;
+ if attr and FILE_ATTRIBUTE_DIRECTORY <> 0 then
begin
- Result := E_INVALIDARG; - // get the contact information - mii.cbSize := sizeof(TMenuItemInfo); - mii.fMask := MIIM_ID or MIIM_DATA; - if GetMenuItemInfo(Self^.hRootMenu, Self^.idCmdFirst + idxCmd, False, mii) then - begin - // get the pointer - Integer(psd) := mii.dwItemData; - // the ID stored in the item pointer and the ID for the menu must match - if (psd = nil) or (psd^.wID <> mii.wID) then + // add the directory
+ lstrcpya(szBuf, args.szFile);
+ ReAllocMem(args.files, (args.count + 1) * sizeof(PChar));
+ GetMem(p, strlen(szBuf) + 1);
+ lstrcpya(p, szBuf);
+ args.files^[args.count] := p;
+ inc(args.count);
+ // tack on ending search token
+ lstrcata(szBuf, '\*');
+ hFind := FindFirstFile(szBuf, fd);
+ while True do
+ begin
+ if fd.cFileName[0] <> '.' then
+ begin
+ lstrcpya(szBuf, args.szFile);
+ lstrcata(szBuf, '\');
+ lstrcata(szBuf, fd.cFileName);
+ // keep a copy of the current thing being processed
+ szThis := args.szFile;
+ args.szFile := szBuf;
+ cchThis := args.cch;
+ args.cch := strlen(szBuf) + 1;
+ // recurse
+ Result := AddToList(args);
+ // restore
+ args.szFile := szThis;
+ args.cch := cchThis;
+ if Result then
+ break;
+ end; // if
+ if not FindNextFile(hFind, fd) then
+ break;
+ end; // while
+ FindClose(hFind);
+ end
+ else
+ begin
+ // add the file
+ ReAllocMem(args.files, (args.count + 1) * sizeof(PChar));
+ GetMem(p, args.cch);
+ lstrcpya(p, args.szFile);
+ args.files^[args.count] := p;
+ inc(args.count);
+ end; // if
+ end;
+end;
+
+procedure MainThreadIssueTransfer(p: PAddArgList); stdcall;
+{$DEFINE SHL_IDC}
+{$DEFINE SHL_KEYS}
+{$INCLUDE shlc.inc}
+{$UNDEF SHL_KEYS}
+{$UNDEF SHL_IDC}
+begin
+ DBWriteContactSettingByte(p^.hContact, SHLExt_Name, SHLExt_MRU, 1);
+ CallService(MS_FILE_SENDSPECIFICFILES, p^.hContact, lParam(p^.files));
+ SetEvent(p^.hEvent);
+end;
+
+function IssueTransferThread(pipch: PHeaderIPC): Cardinal; stdcall;
+var
+ szBuf: array [0 .. MAX_PATH] of Char;
+ pct: PSlotIPC;
+ args: TAddArgList;
+ bQuit: LongBool;
+ j, c: Cardinal;
+ p: Pointer;
+ hMainThread: THandle;
+begin
+ Thread_Push(0,0);
+ hMainThread := THandle(pipch^.Param);
+ GetCurrentDirectory(sizeof(szBuf), szBuf);
+ args.count := 0;
+ args.files := nil;
+ pct := pipch^.DataPtr;
+ bQuit := False;
+ while pct <> nil do
+ begin
+ if (pct^.cbSize <> sizeof(TSlotIPC)) then
+ break;
+ args.szFile := PChar(Integer(pct) + sizeof(TSlotIPC));
+ args.hContact := pct^.hContact;
+ args.cch := pct^.cbStrSection + 1;
+ bQuit := AddToList(args);
+ if bQuit then
+ break;
+ pct := pct^.Next;
+ end; // while
+ if args.files <> nil then
+ begin
+ ReAllocMem(args.files, (args.count + 1) * sizeof(PChar));
+ args.files^[args.count] := nil;
+ inc(args.count);
+ if (not bQuit) then
+ begin
+ args.hEvent := CreateEvent(nil, True, False, nil);
+ QueueUserAPC(@MainThreadIssueTransfer, hMainThread, DWORD(@args));
+ while True do
+ begin
+ if WaitForSingleObjectEx(args.hEvent, INFINITE, True) <> WAIT_IO_COMPLETION then
+ break;
+ end;
+ CloseHandle(args.hEvent);
+ end; // if
+ c := args.count - 1;
+ for j := 0 to c do
+ begin
+ p := args.files^[j];
+ if p <> nil then
+ FreeMem(p);
+ end;
+ FreeMem(args.files);
+ end;
+ SetCurrentDirectory(szBuf);
+ FreeMem(pipch);
+ CloseHandle(hMainThread);
+ Thread_Pop();
+ ExitThread(0);
+end;
+
+type
+
+ PSlotInfo = ^TSlotInfo;
+
+ TSlotInfo = record
+ hContact: THandle;
+ hProto: Cardinal;
+ dwStatus: Integer; // will be aligned anyway
+ end;
+
+ TSlotArray = array [0 .. $FFFFFF] of TSlotInfo;
+ PSlotArray = ^TSlotArray;
+
+function SortContact(var Item1, Item2: TSlotInfo): Integer; stdcall;
+begin
+ Result := CallService(MS_CLIST_CONTACTSCOMPARE, Item1.hContact, Item2.hContact);
+end;
+
+// from FP FCL
+
+procedure QuickSort(FList: PSlotArray; L, R: LongInt);
+var
+ i, j: LongInt;
+ p, q: TSlotInfo;
+begin
+ repeat
+ i := L;
+ j := R;
+ p := FList^[(L + R) div 2];
+ repeat
+ while SortContact(p, FList^[i]) > 0 do
+ inc(i);
+ while SortContact(p, FList^[j]) < 0 do
+ dec(j);
+ if i <= j then
+ begin
+ q := FList^[i];
+ FList^[i] := FList^[j];
+ FList^[j] := q;
+ inc(i);
+ dec(j);
+ end; // if
+ until i > j;
+ if L < j then
+ QuickSort(FList, L, j);
+ L := i;
+ until i >= R;
+end;
+
+{$DEFINE SHL_KEYS}
+{$INCLUDE shlc.inc}
+{$UNDEF SHL_KEYS}
+
+procedure ipcGetSkinIcons(ipch: PHeaderIPC);
+var
+ protoCount: Integer;
+ pp: ^PPROTOCOLDESCRIPTOR;
+ spi: TSlotProtoIcons;
+ j: Cardinal;
+ pct: PSlotIPC;
+ szTmp: array [0 .. 63] of Char;
+ dwCaps: Cardinal;
+begin
+ if (CallService(MS_PROTO_ENUMPROTOCOLS, wParam(@protoCount), lParam(@pp)) = 0) and
+ (protoCount <> 0) then
+ begin
+ spi.pid := GetCurrentProcessId();
+ while protoCount > 0 do
+ begin
+ if (pp^._type = PROTOTYPE_PROTOCOL) then
+ begin
+ lstrcpya(szTmp, pp^.szName);
+ lstrcata(szTmp, PS_GETCAPS);
+ dwCaps := CallService(szTmp, PFLAGNUM_1, 0);
+ if (dwCaps and PF1_FILESEND) <> 0 then
+ begin
+ pct := ipcAlloc(ipch, sizeof(TSlotProtoIcons));
+ if pct <> nil then
+ begin
+ // capture all the icons!
+ spi.hProto := StrHash(pp^.szName);
+ for j := 0 to 9 do
begin
- //MessageBox(0,'ptr assocated with menu is NULL','',MB_OK); - Exit; - end; //if - end else begin
- //MessageBox(0,'GetMenuItemInfo failed?','',MB_OK); - // couldn't get the info, can't start the transfer - Result := E_INVALIDARG; Exit; - end; //if - // is there an IDataObject instance? - if Self^.pDataObject <> nil then - begin - // OpenEvent() the work object to see if the instance is still around - hTransfer := OpenEvent(EVENT_ALL_ACCESS, False, PChar(CreateProcessUID(psd^.pid))); - if hTransfer <> 0 then - begin - // map the ipc file again - hMap := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, IPC_PACKET_SIZE, IPC_PACKET_NAME); - if (hMap <> 0) and (GetLastError <> ERROR_ALREADY_EXISTS) then - begin - // map it to process - pipch := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); - if pipch <> nil then - begin - // create the name of the object to be signalled by the ST - strcpy(pipch^.SignalEventName, PChar(CreateUID())); - // create it - hReply := CreateEvent(nil, False, False, pipch^.SignalEventName); - if hReply <> 0 then - begin
- if dtCommand in psd^.fTypes then
- begin
- if Assigned(psd^.MenuCommandCallback) then
- Result := psd^.MenuCommandCallback(pipch, hTransfer, hReply, psd);
- end
- else
- begin
- - // prepare the buffer - ipcPrepareRequests(IPC_PACKET_SIZE, pipch, REQUEST_XFRFILES); - // get all the files into the packet - if ipcGetFiles(pipch, Self^.pDataObject, psd^.hContact) = S_OK then - begin - // need to wait for the ST to open the mapping object - // since if we close it before it's opened it the data it - // has will be undefined - replyBits := ipcSendRequest(hTransfer, hReply, pipch, 200); - if replyBits <> REPLY_FAIL then - begin - // they got the files! - Result := S_OK; - end; //if - end;
-
- end; - // close the work object name - CloseHandle(hReply); - end; //if - // unmap it from this process - UnmapViewOfFile(pipch); - end; //if - // close the map - CloseHandle(hMap); - end; //if - // close the handle to the ST object name - CloseHandle(hTransfer); - end; //if - end //if; - end; - - function TShlComRec_InvokeCommand(Self: PContextMenu3_Interface; - var lpici: TCMInvokeCommandInfo): HResult; stdcall; - begin - Result := RequestTransfer(Self^.ptrInstance, LOWORD(Integer(lpici.lpVerb))); - end; - - function TShlComRec_HandleMenuMsgs(Self: PContextMenu3_Interface; - uMsg: UINT; wParam: WPARAM; lParam: LPARAM; pResult: PLResult): HResult; - const - WM_DRAWITEM = $002B; - WM_MEASUREITEM = $002C; - var - dwi: PDrawItemStruct; - msi: PMeasureItemStruct; - psd: PMenuDrawInfo; - ncm: TNonClientMetrics; - hOldFont: THandle; - hFont: THandle; - tS: TSize; - dx: Integer; - hBr: HBRUSH; - icorc: TRect; - hMemDC: HDC; - begin - pResult^ := Integer(True); - if (uMsg = WM_DRAWITEM) and (wParam = 0) then - begin - // either a main sub menu, a group menu or a contact - dwi := PDrawItemStruct(lParam); - Integer(psd) := dwi^.itemData; - // don't fill - SetBkMode(dwi^.hDC, TRANSPARENT); - // where to draw the icon? - icorc.Left := 0; - // center it - with dwi^ do - icorc.Top := rcItem.Top + ((rcItem.Bottom - rcItem.Top) div 2) - (16 div 2); - icorc.Right := icorc.Left + 16; - icorc.Bottom := icorc.Top + 16; - // draw for groups - if (dtGroup in psd^.fTypes) or (dtEntry in psd^.fTypes) then - begin - hBr := GetSysColorBrush(COLOR_MENU); - FillRect(dwi^.hDC, dwi^.rcItem, hBr); - DeleteObject(hBr); - // - if (ODS_SELECTED and dwi^.itemState = ODS_SELECTED) then - begin - // only do this for entry menu types otherwise a black mask - // is drawn under groups - hBr := GetSysColorBrush(COLOR_HIGHLIGHT); - FillRect(dwi^.hDC, dwi^.rcItem, hBr); - DeleteObject(hBr); - SetTextColor(dwi^.hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); - end; //if - // draw icon - with dwi^, icorc do - begin - if (ODS_SELECTED and dwi^.itemState) = ODS_SELECTED then - begin - hBr := GetSysColorBrush(COLOR_HIGHLIGHT); - end else begin - hBr := GetSysColorBrush(COLOR_MENU); - end; //if - DrawIconEx(hDC, Left+1, Top, psd^.hStatusIcon, - 16, 16, // width, height - 0, // step - hBr, // brush - DI_NORMAL); - DeleteObject(hBr); - end; //with - // draw the text - with dwi^ do - begin - Inc(rcItem.Left, ((rcItem.Bottom-rcItem.Top)-2)); - DrawText(hDC, psd^.szText, psd^.cch, rcItem, DT_NOCLIP or DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER); - // draw the name of the database text if it's there - if psd^.szProfile <> nil then - begin - GetTextExtentPoint32(dwi^.hDC, psd^.szText, psd^.cch, tS); - Inc(rcItem.Left, tS.cx+8); - SetTextColor(hDC, GetSysColor(COLOR_GRAYTEXT)); - DrawText(hDC, psd^.szProfile, lstrlen(psd^.szProfile), rcItem, DT_NOCLIP or DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER); - end; //if - end; //with - end else - begin - // it's a contact! - hBr := GetSysColorBrush(COLOR_MENU); - FillRect(dwi^.hDC, dwi^.rcItem, hBr); - DeleteObject(hBr); - if ODS_SELECTED and dwi^.itemState = ODS_SELECTED then - begin - hBr := GetSysColorBrush(COLOR_HIGHLIGHT); - FillRect(dwi^.hDC, dwi^.rcItem, hBr); - DeleteObject(hBr); - SetTextColor(dwi^.hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); - end; - // draw icon - with dwi^, icorc do - begin - if (ODS_SELECTED and dwi^.itemState) = ODS_SELECTED then - begin - hBr := GetSysColorBrush(COLOR_HIGHLIGHT); - end else begin - hBr := GetSysColorBrush(COLOR_MENU); - end; //if - DrawIconEx(hDC, Left+2, Top, psd^.hStatusIcon, - 16, 16, // width, height - 0, // step - hBr, // brush - DI_NORMAL); - DeleteObject(hBr); - end; //with - // draw the text - with dwi^ do - begin - Inc(rcItem.Left, (rcItem.Bottom-rcItem.Top) + 1); - DrawText(hDC, psd^.szText, psd^.cch, rcItem, DT_NOCLIP or DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER); - end; //with - end; //if - end - else if (uMsg = WM_MEASUREITEM) then - begin - // don't check if it's really a menu - msi := PMeasureItemStruct(lParam); - Integer(psd) := msi^.itemData; - ncm.cbSize := sizeof(TNonClientMetrics); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @ncm, 0); - // create the font used in menus, this font should be cached somewhere really - {$IFDEF FPC} - hFont := CreateFontIndirect(@ncm.lfMenuFont); - {$ELSE} - hFont := CreateFontIndirect(ncm.lfMenuFont); - {$ENDIF} - hMemDC := Self^.ptrInstance^.hMemDC; - // select in the font - hOldFont := SelectObject(hMemDC, hFont); - // default to an icon - dx := 16; - // get the size 'n' account for the icon - GetTextExtentPoint32(hMemDC, psd^.szText, psd^.cch, tS); - Inc(dx, tS.cx); - // main menu item? - if psd^.szProfile <> nil then - begin - GetTextExtentPoint32(hMemDC, psd^.szProfile, lstrlen(psd^.szProfile), tS); - Inc(dx, tS.cx); - end; - // store it - msi^.itemWidth := dx + Integer(ncm.iMenuWidth); - msi^.itemHeight := Integer(ncm.iMenuHeight)+2; - if tS.cy > msi^.itemHeight then Inc(msi^.itemHeight, tS.cy - msi^.itemHeight); - // clean up - SelectObject(hMemDC, hOldFont); - DeleteObject(hFont); - end; - Result := S_OK; - end; - - function TShlComRec_HandleMenuMsg(Self: PContextMenu3_Interface; - uMsg: UINT; wParam: WPARAM; lParam: LPARAM): HResult; stdcall; - var - Dummy: HResult; - begin - Result := TShlComRec_HandleMenuMsgs(Self, uMsg, wParam, lParam, @Dummy); - end; - - function TShlComRec_HandleMenuMsg2(Self: PContextMenu3_Interface; - uMsg: UINT; wParam: WPARAM; lParam: LPARAM; plResult: Pointer{^LResult}): HResult; stdcall; - var - Dummy: HResult; - begin - // this will be null if a return value isn't needed. - if plResult = nil then plResult := @Dummy; - Result := TShlComRec_HandleMenuMsgs(Self, uMsg, wParam, lParam, plResult); - end; - - function TShlComRec_Create: PShlComRec; - var - DC: HDC; - begin - New(Result); - { build all the function tables for interfaces } - with Result^.ShellExtInit_Interface do - begin - { this is only owned by us... } - ptrVTable := @vTable; - { IUnknown } - vTable.QueryInterface := @TShlComRec_QueryInterface; - vTable.AddRef := @TShlComRec_AddRef; - vTable.Release := @TShlComRec_Release; - { IShellExtInit } - vTable.Initialise := @TShlComRec_Initialise; - { instance of a TShlComRec } - ptrInstance := Result; - end; - with Result^.ContextMenu3_Interface do - begin - ptrVTable := @vTable; - { IUnknown } - vTable.QueryInterface := @TShlComRec_QueryInterface; - vTable.AddRef := @TShlComRec_AddRef; - vTable.Release := @TShlComRec_Release; - { IContextMenu } - vTable.QueryContextMenu := @TShlComRec_QueryContextMenu; - vTable.InvokeCommand := @TShlComRec_InvokeCommand; - vTable.GetCommandString := @TShlComRec_GetCommandString; - { IContextMenu2 } - vTable.HandleMenuMsg := @TShlComRec_HandleMenuMsg; - { IContextMenu3 } - vTable.HandleMenuMsg2 := @TShlComRec_HandleMenuMsg2; - { instance data } - ptrInstance := Result; - end; - { initalise variables } - Result^.RefCount := 1; - Result^.hDllHeap := HeapCreate(0, 0, 0); - Result^.hRootMenu := 0;
- Result^.hRecentMenu := 0;
- Result^.RecentCount := 0; - Result^.idCmdFirst := 0; - Result^.pDataObject := nil; - Result^.ProtoIcons := nil; - Result^.ProtoIconsCount := 0; - // create an inmemory DC - DC := GetDC(0); - Result^.hMemDC := CreateCompatibleDC(DC); - ReleaseDC(0,DC); - { keep count on the number of objects } - Inc(dllpublic.ObjectCount); - end; - -{ IClassFactory } - -type - - PVTable_IClassFactory = ^TVTable_IClassFactory; - TVTable_IClassFactory = record - { IUnknown } - QueryInterface: Pointer; - AddRef: Pointer; - Release: Pointer; - { IClassFactory } - CreateInstance: Pointer; - LockServer: Pointer; - end; - PClassFactoryRec = ^TClassFactoryRec; - TClassFactoryRec = record - ptrVTable: PVTable_IClassFactory; - vTable: TVTable_IClassFactory; - {fields} - RefCount: LongInt; - end; - - function TClassFactoryRec_QueryInterface(Self: PClassFactoryRec; - const IID: TIID; var Obj): HResult; stdcall; - begin - Pointer(Obj) := nil; - Result := E_NOTIMPL; - end; - - function TClassFactoryRec_AddRef(Self: PClassFactoryRec): LongInt; stdcall; - begin - Inc(Self^.RefCount); - Result := Self^.RefCount; - end; - - function TClassFactoryRec_Release(Self: PClassFactoryRec): LongInt; stdcall; - begin - Dec(Self^.RefCount); - Result := Self^.RefCount; - if Result = 0 then - begin - Dispose(Self); - Dec(dllpublic.FactoryCount); - end; {if} - end; - - function TClassFactoryRec_CreateInstance(Self: PClassFactoryRec; - unkOuter: Pointer; const IID: TIID; var Obj): HResult; stdcall; - var - ShlComRec: PShlComRec; - begin - Pointer(Obj) := nil; - Result := CLASS_E_NOAGGREGATION; - if unkOuter = nil then - begin - { Before Vista, the system queried for a IShell interface then queried for a context menu, Vista now - queries for a context menu (or a shell menu) then QI()'s the other interface } - if IsEqualIID(IID, IID_IContextMenu) then - begin - Result := S_OK; - ShlComRec := TShlComRec_Create; - Pointer(Obj) := @ShlComRec^.ContextMenu3_Interface; - end; - if IsEqualIID(IID, IID_IShellExtInit) then - begin - Result := S_OK; - ShlComRec := TShlComRec_Create; - Pointer(Obj) := @ShlComRec^.ShellExtInit_Interface; - end; //if - end; //if - end; - function TClassFactoryRec_LockServer(Self: PClassFactoryRec; fLock: BOOL): HResult; stdcall; - begin - Result := E_NOTIMPL; - end; - - function TClassFactoryRec_Create: PClassFactoryRec; - begin - New(Result); - Result^.ptrVTable := @Result^.vTable; - { IUnknown } - Result^.vTable.QueryInterface := @TClassFactoryRec_QueryInterface; - Result^.vTable.AddRef := @TClassFactoryRec_AddRef; - Result^.vTable.Release := @TClassFactoryRec_Release; - { IClassFactory } - Result^.vTable.CreateInstance := @TClassFactoryRec_CreateInstance; - Result^.vTable.LockServer := @TClassFactoryRec_LockServer; - { inital the variables } - Result^.RefCount := 1; - { count the number of factories } - Inc(dllpublic.FactoryCount); - end; - - // - // IPC part - // - - - type - PFileList = ^TFileList; - TFileList = array[0..0] of PChar; - PAddArgList = ^TAddArgList; - TAddArgList = record - szFile: PChar; // file being processed - cch: Cardinal; // it's length (with space for NULL char) - count: Cardinal; // number we have so far - files: PFileList; - hContact: THandle; - hEvent: THandle; - end; - - function AddToList(var args: TAddArgList): LongBool; - var - attr: Cardinal; - p: Pointer; - hFind: THandle; - fd: TWIN32FINDDATA; - szBuf: array[0..MAX_PATH] of Char; - szThis: PChar; - cchThis: Cardinal; - begin - Result := False; - attr := GetFileAttributes(args.szFile); - if (attr <> $FFFFFFFF) and ((attr and FILE_ATTRIBUTE_HIDDEN) = 0) then - begin - if args.count mod 10 = 5 then - begin - if CallService(MS_SYSTEM_TERMINATED,0,0) <> 0 then - begin - Result := True; Exit; - end; //if - end; - if attr and FILE_ATTRIBUTE_DIRECTORY <> 0 then - begin - // add the directory - strcpy(szBuf,args.szFile); - ReallocMem(args.files,(args.count+1)*sizeof(PChar)); - GetMem(p,strlen(szBuf)+1); - strcpy(p,szBuf); - args.files^[args.count] := p; - inc(args.count); - // tack on ending search token - strcat(szBuf,'\*'); - hFind := FindFirstFile(szBuf,fd); - while True do - begin - if fd.cFileName[0] <> '.' then - begin - strcpy(szBuf,args.szFile); - strcat(szBuf,'\'); - strcat(szBuf,fd.cFileName); - // keep a copy of the current thing being processed - szThis := args.szFile; args.szFile := szBuf; - cchThis := args.cch; args.cch := strlen(szBuf)+1; - // recurse - Result := AddToList(args); - // restore - args.szFile := szThis; - args.cch := cchThis; - if Result then Break; - end; //if - if not FindNextFile(hFind,fd) then Break; - end; //while - FindClose(hFind); - end else begin - // add the file - ReallocMem(args.files,(args.count+1)*sizeof(PChar)); - GetMem(p,args.cch); - strcpy(p,args.szFile); - args.files^[args.count] := p; - inc (args.count); - end; //if - end; - end; - - procedure MainThreadIssueTransfer(p: PAddArgList); stdcall;
- {$define SHL_IDC}
- {$define SHL_KEYS}
- {$include shlc.inc}
- {$undef SHL_KEYS}
- {$undef SHL_IDC} - begin
- DBWriteContactSettingByte(p^.hContact, SHLExt_Name, SHLExt_MRU, 1); - CallService(MS_FILE_SENDSPECIFICFILES,p^.hContact,lParam(p^.files)); - SetEvent(p^.hEvent); - end; - - function IssueTransferThread(pipch: PHeaderIPC): Cardinal; stdcall; - var - szBuf: array[0..MAX_PATH] of Char; - pct: PSlotIPC; - args: TAddArgList; - bQuit: LongBool; - j,c: Cardinal; - p: Pointer; - hMainThread: THandle; - begin - CallService(MS_SYSTEM_THREAD_PUSH,0,0); - hMainThread := THandle(pipch^.Param); - GetCurrentDirectory(sizeof(szBuf),szBuf); - args.count := 0; - args.files := nil; - pct := pipch^.DataPtr; - bQuit := False; - while pct <> nil do - begin - if (pct^.cbSize <> sizeof(TSlotIPC)) then break; - args.szFile := PChar(Integer(pct) + sizeof(TSlotIPC)); - args.hContact := pct^.hContact; - args.cch := pct^.cbStrSection+1; - bQuit := AddToList(args); - if bQuit then Break; - pct := pct^.next; - end; //while - if args.files <> nil then - begin - ReallocMem(args.files,(args.count+1)*sizeof(PChar)); - args.files^[args.count] := nil; - inc (args.count); - if (not bQuit) then - begin - args.hEvent := CreateEvent(nil, True, False, nil); - QueueUserAPC(@MainThreadIssueTransfer,hMainThread,DWORD(@args)); - while True do - begin - if WaitForSingleObjectEx(args.hEvent,INFINITE,True) <> WAIT_IO_COMPLETION then Break; - end; - CloseHandle(args.hEvent); - end; //if - c := args.count-1; - for j := 0 to c do - begin - p := args.files^[j]; - if p <> nil then FreeMem(p); - end; - FreeMem(args.files); - end; - SetCurrentDirectory(szBuf); - FreeMem(pipch); - CloseHandle(hMainThread); - CallService(MS_SYSTEM_THREAD_POP,0,0); - ExitThread(0); - end; - -type - - PSlotInfo = ^TSlotInfo; - TSlotInfo = record - hContact: THandle; - hProto: Cardinal; - dwStatus: Integer; // will be aligned anyway - end; - TSlotArray = array[0..$FFFFFF] of TSlotInfo; - PSlotArray = ^TSlotArray; - - function SortContact(var Item1, Item2: TSlotInfo): Integer; stdcall; - begin - Result := PluginLink^.CallService(MS_CLIST_CONTACTSCOMPARE, item1.hContact, item2.hContact); - end; - - // from FP FCL - - procedure QuickSort (FList: PSlotArray; L, R: LongInt); - var - I, J: LongInt; - P, Q: TSlotInfo; - begin - repeat - I := L; - J := R; - P := FList^[ (L+R) div 2 ]; - repeat - while SortContact(P, FList^[i]) > 0 do Inc(i); - while SortContact(P, FList^[j]) < 0 do Dec(j); - if I <= J then - begin - Q := FList^[I]; - FList^[I] := FList^[J]; - FList^[J] := Q; - Inc(I); - Dec(J); - end; //if - until I > J; - if L < J then QuickSort (FList, L, J); - L := I; - until I >= R; - end; - - {$define SHL_KEYS} - {$include shlc.inc} - {$undef SHL_KEYS} - - procedure ipcGetSkinIcons(ipch: PHeaderIPC); - var - protoCount: Integer; - pp: ^PPROTOCOLDESCRIPTOR; - spi: TSlotProtoIcons; - j: Cardinal; - pct: PSlotIPC; - szTmp: array[0..63] of Char; - dwCaps: Cardinal; - begin - if (CallService(MS_PROTO_ENUMPROTOCOLS,wParam(@protoCount),lParam(@pp)) = 0) and (protoCount <> 0) then - begin - spi.pid := GetCurrentProcessId(); - while protoCount > 0 do - begin - if (pp^.type_ = PROTOTYPE_PROTOCOL) then - begin - strcpy(szTmp,pp^.szName); - strcat(szTmp,PS_GETCAPS); - dwCaps := CallService(szTmp,PFLAGNUM_1,0); - if (dwCaps and PF1_FILESEND) <> 0 then - begin - pct := ipcAlloc(ipch,sizeof(TSlotProtoIcons)); - if pct <> nil then - begin - // capture all the icons! - spi.hProto := StrHash(pp^.szName); - for j := 0 to 9 do - begin - spi.hIcons[j] := LoadSkinnedProtoIcon(pp^.szName,ID_STATUS_OFFLINE+j); - end; //for - pct^.fType := REQUEST_NEWICONS; - CopyMemory(Pointer(Integer(pct)+sizeof(TSlotIPC)),@spi,sizeof(TSlotProtoIcons)); - if ipch^.NewIconsBegin = nil then ipch^.NewIconsBegin := pct; - end; //if - end; //if - end; //if - inc (pp); - dec (protoCount); - end; //while - end; //if - // add Miranda icon - pct := ipcAlloc(ipch, sizeof(TSlotProtoIcons)); - if pct <> nil then - begin - ZeroMemory(@spi.hIcons, sizeof(spi.hIcons)); - spi.hProto := 0; // no protocol - spi.hIcons[0] := LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); - pct^.fType := REQUEST_NEWICONS; - CopyMemory(Pointer(Integer(pct)+sizeof(TSlotIPC)),@spi,sizeof(TSlotProtoIcons)); - if ipch^.NewIconsBegin = nil then ipch^.NewIconsBegin := pct; - end; //if - end; - - function ipcGetSortedContacts(ipch: PHeaderIPC; pSlot: pint; bGroupMode: Boolean): Boolean; - var - dwContacts: Cardinal; - pContacts: PSlotArray; - hContact: THandle; - I: Integer; - dwOnline: Cardinal; - szProto: PChar; - dwStatus: Integer; - pct: PSlotIPC; - szContact: PChar; - dbv: TDBVariant; - bHideOffline: Boolean; - szTmp: array[0..63] of Char; - dwCaps: Cardinal; - szSlot: PChar; - n, rc, cch: Cardinal; - begin - Result := False; - // hide offliners? - bHideOffline := DBGetContactSettingByte(0, 'CList', 'HideOffline', 0) = 1; - // do they wanna hide the offline people anyway? - if DBGetContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoOffline, 0) = 1 then - begin - // hide offline people - bHideOffline := True; - end; - // get the number of contacts - dwContacts := PluginLink^.CallService(MS_DB_CONTACT_GETCOUNT, 0, 0); - if dwContacts = 0 then Exit; - // get the contacts in the array to be sorted by status, trim out anyone - // who doesn't wanna be seen. - GetMem(pContacts, (dwContacts+2) * sizeof(TSlotInfo)); - i := 0; - dwOnline := 0; - hContact := PluginLink^.CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while (hContact <> 0) do - begin - if i >= dwContacts then Break; - (* do they have a running protocol? *) - Integer(szProto) := PluginLink^.CallService(MS_PROTO_GETCONTACTBASEPROTO, hContact, 0); - if szProto <> nil then - begin - (* does it support file sends? *) - strcpy(szTmp, szProto); - strcat(szTmp, PS_GETCAPS); - dwCaps := CallService(szTmp,PFLAGNUM_1,0); - if (dwCaps and PF1_FILESEND) = 0 then - begin - hContact := CallService(MS_DB_CONTACT_FINDNEXT,hContact,0); - continue; - end; - dwStatus := DBGetContactSettingWord(hContact, szProto, 'Status', ID_STATUS_OFFLINE); - if dwStatus <> ID_STATUS_OFFLINE then Inc(dwOnline) - else if bHideOffline then - begin - hContact := PluginLink^.CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0); - continue; - end; //if - // is HIT on? - if BST_UNCHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseHITContacts, BST_UNCHECKED) then - begin - // don't show people who are "Hidden" "NotOnList" or Ignored - if (DBGetContactSettingByte(hContact, 'CList', 'Hidden', 0) = 1) - or (DBGetContactSettingByte(hContact, 'CList', 'NotOnList', 0) = 1) - or (PluginLink^.CallService(MS_IGNORE_ISIGNORED, hContact, IGNOREEVENT_MESSAGE or IGNOREEVENT_URL or IGNOREEVENT_FILE) <> 0) then - begin - hContact := PluginLink^.CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0); - continue; - end; //if - end; //if - // is HIT2 off? - if BST_UNCHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseHIT2Contacts, BST_UNCHECKED) then - begin - if DBGetContactSettingWord(hContact, szProto, 'ApparentMode', 0) = ID_STATUS_OFFLINE then - begin - hContact := PluginLink^.CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0); - continue; - end; //if - end; //if - // store - pContacts^[i].hContact := hContact; - pContacts^[i].dwStatus := dwStatus; - pContacts^[i].hProto := StrHash(szProto); - Inc(i); - end else begin - // contact has no protocol! - end; //if - hContact := PluginLink^.CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0); - end; //while - // if no one is online and the CList isn't showing offliners, quit - if (dwOnline = 0) and (bHideOffline) then - begin - FreeMem(pContacts); Exit; - end; //if - dwContacts := i; i := 0; - // sort the array - QuickSort(pContacts, 0, dwContacts-1); - // create an IPC slot for each contact and store display name, etc - while i < dwContacts do - begin - Integer(szContact) := PluginLink^.CallService(MS_CLIST_GETCONTACTDISPLAYNAME, pContacts^[i].hContact, 0); - if (szContact <> nil) then - begin - n := 0; - rc := 1; - if bGroupMode then - begin - rc := DBGetContactSetting(pContacts^[i].hContact,'CList','Group',@dbv); - if rc = 0 then - begin - n := lstrlen(dbv.pszVal)+1; - end; - end; //if - cch := lstrlen(szContact)+1; - pct := ipcAlloc(ipch, cch + 1 + n); - if pct = nil then - begin - DBFreeVariant(@dbv); - break; - end; - // lie about the actual size of the TSlotIPC - pct^.cbStrSection := cch; - szSlot := PChar(Integer(pct) + sizeof(TSlotIPC)); - strcpy(szSlot, szContact); - pct^.fType := REQUEST_CONTACTS; - pct^.hContact := pContacts^[i].hContact; - pct^.Status := pContacts^[i].dwStatus; - pct^.hProto := pContacts^[i].hProto;
- pct^.MRU := DBGetContactSettingByte(pct^.hContact, SHLExt_Name, SHLExt_MRU, 0); - if ipch^.ContactsBegin = nil then ipch^.ContactsBegin := pct; - inc(szSlot,cch+1); - if rc=0 then - begin - pct^.hGroup := StrHash(dbv.pszVal); - strcpy(szSlot,dbv.pszVal); - DBFreeVariant(@dbv); - end else begin - pct^.hGroup := 0; - szSlot^ := #0; - end; - inc(pSlot^); - end; //if - Inc(i); - end; //while - FreeMem(pContacts); - // - Result := True; + spi.hIcons[j] := LoadSkinnedProtoIcon(pp^.szName, ID_STATUS_OFFLINE + j);
+ end; // for
+ pct^.fType := REQUEST_NEWICONS;
+ CopyMemory(Pointer(Integer(pct) + sizeof(TSlotIPC)), @spi, sizeof(TSlotProtoIcons));
+ if ipch^.NewIconsBegin = nil then
+ ipch^.NewIconsBegin := pct;
+ end; // if
+ end; // if
+ end; // if
+ inc(pp);
+ dec(protoCount);
+ end; // while
+ end; // if
+ // add Miranda icon
+ pct := ipcAlloc(ipch, sizeof(TSlotProtoIcons));
+ if pct <> nil then
+ begin
+ ZeroMemory(@spi.hIcons, sizeof(spi.hIcons));
+ spi.hProto := 0; // no protocol
+ spi.hIcons[0] := LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ pct^.fType := REQUEST_NEWICONS;
+ CopyMemory(Pointer(Integer(pct) + sizeof(TSlotIPC)), @spi, sizeof(TSlotProtoIcons));
+ if ipch^.NewIconsBegin = nil then
+ ipch^.NewIconsBegin := pct;
+ end; // if
+end;
+
+function ipcGetSortedContacts(ipch: PHeaderIPC; pSlot: pint; bGroupMode: Boolean): Boolean;
+var
+ dwContacts: Cardinal;
+ pContacts: PSlotArray;
+ hContact: THandle;
+ i: Integer;
+ dwOnline: Cardinal;
+ szProto: PChar;
+ dwStatus: Integer;
+ pct: PSlotIPC;
+ szContact: PChar;
+ dbv: TDBVariant;
+ bHideOffline: Boolean;
+ szTmp: array [0 .. 63] of Char;
+ dwCaps: Cardinal;
+ szSlot: PChar;
+ n, rc, cch: Cardinal;
+begin
+ Result := False;
+ // hide offliners?
+ bHideOffline := DBGetContactSettingByte(0, 'CList', 'HideOffline', 0) = 1;
+ // do they wanna hide the offline people anyway?
+ if DBGetContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoOffline, 0) = 1 then
+ begin
+ // hide offline people
+ bHideOffline := True;
+ end;
+ // get the number of contacts
+ dwContacts := CallService(MS_DB_CONTACT_GETCOUNT, 0, 0);
+ if dwContacts = 0 then
+ Exit;
+ // get the contacts in the array to be sorted by status, trim out anyone
+ // who doesn't wanna be seen.
+ GetMem(pContacts, (dwContacts + 2) * sizeof(TSlotInfo));
+ i := 0;
+ dwOnline := 0;
+ hContact := CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact <> 0) do
+ begin
+ if i >= dwContacts then
+ break;
+ (* do they have a running protocol? *)
+ int_ptr(szProto) := CallService(MS_PROTO_GETCONTACTBASEPROTO, hContact, 0);
+ if szProto <> nil then
+ begin
+ (* does it support file sends? *)
+ lstrcpya(szTmp, szProto);
+ lstrcata(szTmp, PS_GETCAPS);
+ dwCaps := CallService(szTmp, PFLAGNUM_1, 0);
+ if (dwCaps and PF1_FILESEND) = 0 then
+ begin
+ hContact := CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0);
+ continue;
+ end;
+ dwStatus := DBGetContactSettingWord(hContact, szProto, 'Status', ID_STATUS_OFFLINE);
+ if dwStatus <> ID_STATUS_OFFLINE then
+ inc(dwOnline)
+ else if bHideOffline then
+ begin
+ hContact := CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0);
+ continue;
+ end; // if
+ // is HIT on?
+ if BST_UNCHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseHITContacts,
+ BST_UNCHECKED) then
+ begin
+ // don't show people who are "Hidden" "NotOnList" or Ignored
+ if (DBGetContactSettingByte(hContact, 'CList', 'Hidden', 0) = 1) or
+ (DBGetContactSettingByte(hContact, 'CList', 'NotOnList', 0) = 1) or
+ (CallService(MS_IGNORE_ISIGNORED, hContact, IGNOREEVENT_MESSAGE or
+ IGNOREEVENT_URL or IGNOREEVENT_FILE) <> 0) then
+ begin
+ hContact := CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0);
+ continue;
+ end; // if
+ end; // if
+ // is HIT2 off?
+ if BST_UNCHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseHIT2Contacts,
+ BST_UNCHECKED) then
+ begin
+ if DBGetContactSettingWord(hContact, szProto, 'ApparentMode', 0) = ID_STATUS_OFFLINE
+ then
+ begin
+ hContact := CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0);
+ continue;
+ end; // if
+ end; // if
+ // store
+ pContacts^[i].hContact := hContact;
+ pContacts^[i].dwStatus := dwStatus;
+ pContacts^[i].hProto := StrHash(szProto);
+ inc(i);
+ end
+ else
+ begin
+ // contact has no protocol!
+ end; // if
+ hContact := CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0);
+ end; // while
+ // if no one is online and the CList isn't showing offliners, quit
+ if (dwOnline = 0) and (bHideOffline) then
+ begin
+ FreeMem(pContacts);
+ Exit;
+ end; // if
+ dwContacts := i;
+ i := 0;
+ // sort the array
+ QuickSort(pContacts, 0, dwContacts - 1);
+ // create an IPC slot for each contact and store display name, etc
+ while i < dwContacts do
+ begin
+ int_ptr(szContact) := CallService(MS_CLIST_GETCONTACTDISPLAYNAME,
+ pContacts^[i].hContact, 0);
+ if (szContact <> nil) then
+ begin
+ n := 0;
+ rc := 1;
+ if bGroupMode then
+ begin
+ rc := DBGetContactSetting(pContacts^[i].hContact, 'CList', 'Group', @dbv);
+ if rc = 0 then
+ begin
+ n := lstrlena(dbv.szVal.a) + 1;
+ end;
+ end; // if
+ cch := lstrlena(szContact) + 1;
+ pct := ipcAlloc(ipch, cch + 1 + n);
+ if pct = nil then
+ begin
+ DBFreeVariant(@dbv);
+ break;
+ end;
+ // lie about the actual size of the TSlotIPC
+ pct^.cbStrSection := cch;
+ szSlot := PChar(Integer(pct) + sizeof(TSlotIPC));
+ lstrcpya(szSlot, szContact);
+ pct^.fType := REQUEST_CONTACTS;
+ pct^.hContact := pContacts^[i].hContact;
+ pct^.Status := pContacts^[i].dwStatus;
+ pct^.hProto := pContacts^[i].hProto;
+ pct^.MRU := DBGetContactSettingByte(pct^.hContact, SHLExt_Name, SHLExt_MRU, 0);
+ if ipch^.ContactsBegin = nil then
+ ipch^.ContactsBegin := pct;
+ inc(szSlot, cch + 1);
+ if rc = 0 then
+ begin
+ pct^.hGroup := StrHash(dbv.szVal.a);
+ lstrcpya(szSlot, dbv.szVal.a);
+ DBFreeVariant(@dbv);
+ end
+ else
+ begin
+ pct^.hGroup := 0;
+ szSlot^ := #0;
+ end;
+ inc(pSlot^);
+ end; // if
+ inc(i);
+ end; // while
+ FreeMem(pContacts);
+ //
+ Result := True;
+end;
+
+// worker thread to clear MRU, called by the IPC bridge
+function ClearMRUThread(notused: Pointer): Cardinal; stdcall;
+{$DEFINE SHL_IDC}
+{$DEFINE SHL_KEYS}
+{$INCLUDE shlc.inc}
+{$UNDEF SHL_KEYS}
+{$UNDEF SHL_IDC}
+var
+ hContact: THandle;
+begin
+ Thread_Push(0,0);
+
+ begin
+ hContact := CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while hContact <> 0 do
+ begin
+ if DBGetContactSettingByte(hContact, SHLExt_Name, SHLExt_MRU, 0) > 0 then
+ begin
+ DBWriteContactSettingByte(hContact, SHLExt_Name, SHLExt_MRU, 0);
+ end;
+ hContact := CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0);
+ end;
+ end;
+ Thread_Pop();
+ ExitThread(0);
+end;
+
+// this function is called from an APC into the main thread
+procedure ipcService(dwParam: DWORD); stdcall;
+label
+ Reply;
+var
+ hMap: THandle;
+ pMMT: PHeaderIPC;
+ hSignal: THandle;
+ pct: PSlotIPC;
+ hContact: THandle;
+ szContact: PChar;
+ Status: int;
+ szBuf: PChar;
+ iSlot: Integer;
+ szGroupStr: array [0 .. 31] of Char;
+ dbv: TDBVariant;
+ bits: pint;
+ HICON: THandle;
+ i: Integer;
+ bGroupMode: Boolean;
+ tid: Cardinal;
+ cloned: PHeaderIPC;
+ szMiranda: PChar;
+begin
+ { try to open the file mapping object the caller must make sure no other
+ running instance is using this file }
+ hMap := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, IPC_PACKET_NAME);
+ If hMap <> 0 then
+ begin
+ { map the file to this process }
+ pMMT := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+ { if it fails the caller should of had some timeout in wait }
+ if (pMMT <> nil) and (pMMT^.cbSize = sizeof(THeaderIPC)) and
+ (pMMT^.dwVersion = PLUGIN_MAKE_VERSION(2, 0, 1, 2)) then
+ begin
+ // toggle the right bits
+ bits := @pMMT^.fRequests;
+ // jump right to a worker thread for file processing?
+ if (bits^ and REQUEST_XFRFILES) = REQUEST_XFRFILES then
+ begin
+ GetMem(cloned, IPC_PACKET_SIZE);
+ // translate from client space to cloned heap memory
+ pMMT^.pServerBaseAddress := pMMT^.pClientBaseAddress;
+ pMMT^.pClientBaseAddress := cloned;
+ CopyMemory(cloned, pMMT, IPC_PACKET_SIZE);
+ ipcFixupAddresses(True, cloned);
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(),
+ @cloned^.Param, THREAD_SET_CONTEXT, False, 0);
+ CloseHandle(CreateThread(nil, 0, @IssueTransferThread, cloned, 0, tid));
+ goto Reply;
+ end;
+ // the request was to clear the MRU entries, we have no return data
+ if (bits^ and REQUEST_CLEARMRU) = REQUEST_CLEARMRU then
+ begin
+ CloseHandle(CreateThread(nil, 0, @ClearMRUThread, nil, 0, tid));
+ goto Reply;
+ end;
+ // the IPC header may have pointers that need to be translated
+ // in either case the supplied data area pointers has to be
+ // translated to this address space.
+ // the server base address is always removed to get an offset
+ // to which the client base is added, this is what ipcFixupAddresses() does
+ pMMT^.pServerBaseAddress := pMMT^.pClientBaseAddress;
+ pMMT^.pClientBaseAddress := pMMT;
+ // translate to the server space map
+ ipcFixupAddresses(True, pMMT);
+ // store the address map offset so the caller can retranslate
+ pMMT^.pServerBaseAddress := pMMT;
+ // return some options to the client
+ if DBGetContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoIcons, 0) <> 0 then
+ begin
+ pMMT^.dwFlags := HIPC_NOICONS;
+ end;
+ // see if we have a custom string for 'Miranda'
+ szMiranda := Translate('Miranda');
+ lstrcpyn(pMMT^.MirandaName, szMiranda, sizeof(pMMT^.MirandaName) - 1);
+
+ // for the MRU menu
+ szBuf := Translate('Recently');
+ lstrcpyn(pMMT^.MRUMenuName, szBuf, sizeof(pMMT^.MRUMenuName) - 1);
+
+ // and a custom string for "clear entries"
+ szBuf := Translate('Clear entries');
+ lstrcpyn(pMMT^.ClearEntries, szBuf, sizeof(pMMT^.ClearEntries) - 1);
+
+ // if the group mode is on, check if they want the CList setting
+ bGroupMode := BST_CHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseGroups,
+ BST_UNCHECKED);
+ if bGroupMode and (BST_CHECKED = DBGetContactSettingByte(0, SHLExt_Name,
+ SHLExt_UseCListSetting, BST_UNCHECKED)) then
+ begin
+ bGroupMode := 1 = DBGetContactSettingByte(0, 'CList', 'UseGroups', 0);
+ end;
+ iSlot := 0;
+ // return profile if set
+ if BST_UNCHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoProfile,
+ BST_UNCHECKED) then
+ begin
+ pct := ipcAlloc(pMMT, 50);
+ if pct <> nil then
+ begin
+ // will actually return with .dat if there's space for it, not what the docs say
+ pct^.Status := STATUS_PROFILENAME;
+ CallService(MS_DB_GETPROFILENAME, 49, Integer(pct) + sizeof(TSlotIPC));
+ end; // if
+ end; // if
+ if (bits^ and REQUEST_NEWICONS) = REQUEST_NEWICONS then
+ begin
+ ipcGetSkinIcons(pMMT);
+ end;
+ if (bits^ and REQUEST_GROUPS = REQUEST_GROUPS) then
+ begin
+ // return contact's grouping if it's present
+ while bGroupMode do
+ begin
+ str(iSlot, szGroupStr);
+ if DBGetContactSetting(0, 'CListGroups', szGroupStr, @dbv) <> 0 then
+ break;
+ pct := ipcAlloc(pMMT, lstrlena(dbv.szVal.a + 1) + 1);
+ // first byte has flags, need null term
+ if pct <> nil then
+ begin
+ if pMMT^.GroupsBegin = nil then
+ pMMT^.GroupsBegin := pct;
+ pct^.fType := REQUEST_GROUPS;
+ pct^.hContact := 0;
+ int_ptr(szBuf) := int_ptr(pct) + sizeof(TSlotIPC); // get the end of the slot
+ lstrcpya(szBuf, dbv.szVal.a + 1);
+ pct^.hGroup := 0;
+ DBFreeVariant(@dbv); // free the string
+ end
+ else
+ begin
+ // outta space
+ DBFreeVariant(@dbv);
+ break;
+ end; // if
+ inc(iSlot);
+ end; { while }
+ // if there was no space left, it'll end on null
+ if pct = nil then
+ bits^ := (bits^ or GROUPS_NOTIMPL) and not REQUEST_GROUPS;
+ end; { if: group request }
+ // SHOULD check slot space.
+ if (bits^ and REQUEST_CONTACTS = REQUEST_CONTACTS) then
+ begin
+ if not ipcGetSortedContacts(pMMT, @iSlot, bGroupMode) then
+ begin
+ // fail if there were no contacts AT ALL
+ bits^ := (bits^ or CONTACTS_NOTIMPL) and not REQUEST_CONTACTS;
+ end; // if
+ end; // if:contact request
+ // store the number of slots allocated
+ pMMT^.Slots := iSlot;
+ Reply:
+ { get the handle the caller wants to be signalled on }
+ hSignal := OpenEvent(EVENT_ALL_ACCESS, False, pMMT^.SignalEventName);
+ { did it open? }
+ If hSignal <> 0 then
+ begin
+ { signal and close }
+ SetEvent(hSignal);
+ CloseHandle(hSignal);
+ end;
+ { unmap the shared memory from this process }
+ UnmapViewOfFile(pMMT);
end;
-
- // worker thread to clear MRU, called by the IPC bridge
- function ClearMRUThread(notused: Pointer): Cardinal; stdcall;
- {$define SHL_IDC}
- {$define SHL_KEYS}
- {$include shlc.inc}
- {$undef SHL_KEYS}
- {$undef SHL_IDC}
- var
- hContact: THandle;
- begin
- CallService(MS_SYSTEM_THREAD_PUSH,0,0);
- begin
- hContact := pluginLink^.CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
- while hContact <> 0 do
- begin
- if DBGetContactSettingByte(hContact, SHLExt_Name, SHLExt_MRU, 0) > 0 then
- begin
- DBWriteContactSettingByte(hContact, SHLExt_Name, SHLExt_MRU, 0);
- end;
- hContact := pluginLink^.CallService(MS_DB_CONTACT_FINDNEXT, hContact, 0);
- end;
- end;
- CallService(MS_SYSTEM_THREAD_POP,0,0);
- ExitThread(0);
- end; -
- // this function is called from an APC into the main thread - procedure ipcService(dwParam: DWORD); stdcall; - label - Reply; - var - hMap: THandle; - pMMT: PHeaderIPC; - hSignal: THandle; - pct: PSlotIPC; - hContact: THandle; - szContact: PChar; - Status: int; - szBuf: PChar; - iSlot: Integer; - szGroupStr: array[0..31] of Char; - dbv: TDBVARIANT; - bits: pint; - hIcon: THandle; - I: Integer; - bGroupMode: Boolean; - tid: Cardinal; - cloned: PHeaderIPC; - szMiranda: PChar; - begin - { try to open the file mapping object the caller must make sure no other - running instance is using this file } - hMap := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, IPC_PACKET_NAME); - If hMap <> 0 then - begin - { map the file to this process } - pMMT := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); - { if it fails the caller should of had some timeout in wait } - if (pMMT <> nil) and (pMMT^.cbSize = sizeof(THeaderIPC)) and (pMMT^.dwVersion = PLUGIN_MAKE_VERSION(2,0,1,2)) then - begin - // toggle the right bits - bits := @pMMT^.fRequests; - // jump right to a worker thread for file processing? - if (bits^ and REQUEST_XFRFILES) = REQUEST_XFRFILES then - begin - GetMem(cloned, IPC_PACKET_SIZE); - // translate from client space to cloned heap memory - pMMT^.pServerBaseAddress := pMMT^.pClientBaseAddress; - pMMT^.pClientBaseAddress := cloned; - CopyMemory(cloned, pMMT, IPC_PACKET_SIZE); - ipcFixupAddresses(True, cloned); - DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),@cloned^.Param,THREAD_SET_CONTEXT,FALSE,0); - CloseHandle(CreateThread(nil,0,@IssueTransferThread,cloned,0,tid)); - goto Reply; - end;
- // the request was to clear the MRU entries, we have no return data
- if (bits^ and REQUEST_CLEARMRU) = REQUEST_CLEARMRU then
- begin
- CloseHandle(CreateThread(nil,0,@ClearMRUThread,nil,0,tid));
- goto reply;
- end; - // the IPC header may have pointers that need to be translated - // in either case the supplied data area pointers has to be - // translated to this address space. - // the server base address is always removed to get an offset - // to which the client base is added, this is what ipcFixupAddresses() does - pMMT^.pServerBaseAddress := pMMT^.pClientBaseAddress; - pMMT^.pClientBaseAddress := pMMT; - // translate to the server space map - ipcFixupAddresses(True, pMMT); - // store the address map offset so the caller can retranslate - pMMT^.pServerBaseAddress := pMMT; - // return some options to the client - if DBGetContactSettingByte(0,SHLExt_Name,SHLExt_ShowNoIcons,0) <> 0 then - begin - pMMT^.dwFlags := HIPC_NOICONS; - end; - // see if we have a custom string for 'Miranda' - szMiranda := Translate('Miranda'); - lstrcpyn(pMMT^.MirandaName,szMiranda,sizeof(pMMT^.MirandaName)-1);
-
- // for the MRU menu
- szBuf := Translate('Recently');
- lstrcpyn(pMMT^.MRUMenuName, szBuf, sizeof(pMMT^.MRUMenuName)-1);
-
- // and a custom string for "clear entries"
- szBuf := Translate('Clear entries');
- lstrcpyn(pMMT^.ClearEntries,szBuf, sizeof(pMMT^.ClearEntries)-1);
- - // if the group mode is on, check if they want the CList setting - bGroupMode := BST_CHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseGroups, BST_UNCHECKED); - if bGroupMode and (BST_CHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseCListSetting, BST_UNCHECKED)) then - begin - bGroupMode := 1 = DBGetContactSettingByte(0, 'CList', 'UseGroups', 0); - end; - iSlot := 0; - // return profile if set - if BST_UNCHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoProfile, BST_UNCHECKED) then - begin - pct := ipcAlloc(pMMT, 50); - if pct <> nil then - begin - // will actually return with .dat if there's space for it, not what the docs say - pct^.Status := STATUS_PROFILENAME; - PluginLink^.CallService(MS_DB_GETPROFILENAME, 49, Integer(pct)+sizeof(TSlotIPC)); - end; //if - end; //if - if (bits^ and REQUEST_NEWICONS) = REQUEST_NEWICONS then - begin - ipcGetSkinIcons(pMMT); - end; - if (bits^ and REQUEST_GROUPS = REQUEST_GROUPS) then - begin - // return contact's grouping if it's present - while bGroupMode do - begin - Str(iSlot, szGroupStr); - if DBGetContactSetting(0, 'CListGroups', szGroupStr, @dbv) <> 0 then Break; - pct := ipcAlloc(pMMT, lstrlen(dbv.pszVal+1)+1); // first byte has flags, need null term - if pct <> nil then - begin - if pMMT^.GroupsBegin = nil then pMMT^.GroupsBegin := pct; - pct^.fType := REQUEST_GROUPS; - pct^.hContact := 0; - Integer (szBuf) := Integer(pct) + sizeof(TSlotIPC); // get the end of the slot - strcpy(szBuf, dbv.pszVal+1); - pct^.hGroup := 0; - DBFreeVariant(@dbv); // free the string - end else begin - // outta space - DBFreeVariant(@dbv); - Break; - end; //if - Inc(iSlot); - end; {while} - // if there was no space left, it'll end on null - if pct = nil then bits^ := (bits^ or GROUPS_NOTIMPL) and not REQUEST_GROUPS; - end; {if: group request} - // SHOULD check slot space. - if (bits^ and REQUEST_CONTACTS = REQUEST_CONTACTS) then - begin - if not ipcGetSortedContacts(pMMT, @iSlot, bGroupMode) then - begin - // fail if there were no contacts AT ALL - bits^ := (bits^ or CONTACTS_NOTIMPL) and not REQUEST_CONTACTS; - end; //if - end; // if:contact request - // store the number of slots allocated - pMMT^.Slots := iSlot; - Reply: - { get the handle the caller wants to be signalled on } - hSignal := OpenEvent(EVENT_ALL_ACCESS, False, pMMT^.SignalEventName); - { did it open? } - If hSignal <> 0 then - begin - { signal and close } - SetEvent(hSignal); CloseHandle(hSignal); - end; - { unmap the shared memory from this process } - UnmapViewOfFile(pMMT); - end; - { close the map file } - CloseHandle(hMap); - end; {if} - // - end; - - function ThreadServer(hMainThread: Pointer): Cardinal; - {$ifdef FPC} - stdcall; - {$endif} - var - hEvent: THandle; - begin - CallService(MS_SYSTEM_THREAD_PUSH,0,0); - hEvent := CreateEvent(nil, False, False, PChar(CreateProcessUID(GetCurrentProcessId()))); - while True do - begin - Result := WaitForSingleObjectEx(hEvent,INFINITE,True); - if Result = WAIT_OBJECT_0 then - begin - QueueUserAPC(@ipcService,THandle(hMainThread),0); - end; //if - if CallService(MS_SYSTEM_TERMINATED,0,0)=1 then Break; - end; //while - CloseHandle(hEvent); - CloseHandle(THandle(hMainThread)); - CallService(MS_SYSTEM_THREAD_POP,0,0); - ExitThread(0); - end; - - procedure InvokeThreadServer; - var - {$ifdef FPC} - TID: LongWord; - {$else} - TID: Cardinal; - {$endif} - var - hMainThread: THandle; - begin - hMainThread := 0; - DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),@hMainThread,THREAD_SET_CONTEXT,FALSE,0); - if hMainThread <> 0 then - begin - {$ifdef FPC} - CloseHandle(CreateThread(nil,0,@ThreadServer,Pointer(hMainThread),0,TID)); - {$else} - CloseHandle(BeginThread(nil,0,@ThreadServer,Pointer(hMainThread),0,TID)); - {$endif} - end; //if - end; - -{ exported functions } - - function DllGetClassObject(const CLSID: TCLSID; const IID: TIID; var Obj): HResult; stdcall; - begin - Pointer(Obj) := nil; - Result := CLASS_E_CLASSNOTAVAILABLE; - if (IsEqualCLSID(CLSID,CLSID_ISHLCOM)) - and (IsEqualIID(IID,IID_IClassFactory)) - and (FindWindow(MIRANDANAME,nil) <> 0) then - begin - Pointer(Obj) := TClassFactoryRec_Create; - Result := S_OK; - end; //if - end; - - function DllCanUnloadNow: HResult; - begin - if ((dllpublic.FactoryCount = 0) and (dllpublic.ObjectCount = 0)) then - begin - Result := S_OK; - end else begin - Result := S_FALSE; - end; //if - end; - -{ helper functions } - -type - - PSHELLEXECUTEINFO = ^TSHELLEXECUTEINFO; - TSHELLEXECUTEINFO = record - cbSize: DWORD; - fMask: LongInt; - hwnd: THandle; - lpVerb: PChar; - lpFile: PChar; - lpParameters: PChar; - lpDirectory: PChar; - nShow: Integer; - hInstApp: THandle; - lpIDLIst: Pointer; - lpClass: PChar; - hKey: THandle; - dwHotKey: DWORD; - hIcon: THandle; // is union - hProcess: THandle; - end; - - function ShellExecuteEx(var se: TSHELLEXECUTEINFO): Boolean; stdcall; external 'shell32.dll' name 'ShellExecuteExA'; - - function wsprintfs(lpOut, lpFmt: PChar; ArgS: PChar): Integer; cdecl; external 'user32.dll' name 'wsprintfA'; - - function RemoveCOMRegistryEntries: HResult; - var - hRootKey: HKEY; - begin - if RegOpenKeyEx(HKEY_CLASSES_ROOT, 'miranda.shlext', 0, KEY_READ, hRootKey) = ERROR_SUCCESS then - begin - (* need to delete the subkey before the parent key is deleted under NT/2000/XP *) - RegDeleteKey(hRootKey, 'CLSID'); - (* close the key *) - RegCloseKey(hRootKey); - (* delete it *) - if RegDeleteKey(HKEY_CLASSES_ROOT, 'miranda.shlext') <> ERROR_SUCCESS then - begin - MessageBox(0, 'Unable to delete registry key for "shlext COM", this key may already be deleted or you may need admin rights.', 'Problem', MB_ICONERROR); - end; //if - end; //if - if RegOpenKeyEx(HKEY_CLASSES_ROOT, '\*\shellex\ContextMenuHandlers', 0, KEY_ALL_ACCESS, hRootKey) = ERROR_SUCCESS then - begin - if RegDeleteKey(hRootKey, 'miranda.shlext') <> ERROR_SUCCESS then - begin - MessageBox(0, 'Unable to delete registry key for "File context menu handlers", this key may already be deleted or you may need admin rights.', 'Problem', MB_ICONERROR); - end; //if - RegCloseKey(hRootKey); - end; //if - if RegOpenKeyEx(HKEY_CLASSES_ROOT, 'Directory\shellex\ContextMenuHandlers', 0, KEY_ALL_ACCESS, hRootKey) = ERROR_SUCCESS then - begin - if RegDeleteKey(hRootKey, 'miranda.shlext') <> ERROR_SUCCESS then - begin - MessageBox(0, 'Unable to delete registry key for "Directory context menu handlers", this key may already be deleted or you may need admin rights.', 'Problem', MB_ICONERROR); - end; //if - RegCloseKey(hRootKey); - end; //if - if ERROR_SUCCESS = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved', 0, KEY_ALL_ACCESS, hRootKey) then - begin - if RegDeleteValue(hRootKey, '{72013A26-A94C-11d6-8540-A5E62932711D}') <> ERROR_SUCCESS then - begin - MessageBox(0, 'Unable to delete registry entry for "Approved context menu handlers", this key may already be deleted or you may need admin rights.', 'Problem', MB_ICONERROR); - end; //if - RegCloseKey(hRootKey); - end; //if - Result := S_OK; - end; - - { called by the options code to remove COM entries, and before that, get permission, if required. - } - - procedure CheckUnregisterServer; - var - sei: TSHELLEXECUTEINFO; - szBuf: array[0..MAX_PATH*2] of Char; - szFileName: array[0..MAX_PATH] of Char; - begin - if not VistaOrLater then - begin - RemoveCOMRegistryEntries(); - Exit; - end; - // launches regsvr to remove the dll under admin. - GetModuleFileName(System.hInstance, szFileName, sizeof(szFileName)); - wsprintfs(szBuf, '/s /u "%s"', szFileName); - ZeroMemory(@sei, sizeof(sei)); - sei.cbSize := sizeof(sei); - sei.lpVerb := 'runas'; - sei.lpFile := 'regsvr32'; - sei.lpParameters := szBuf; - ShellExecuteEx(sei); - Sleep(1000); - RemoveCOMRegistryEntries(); - end; - - { Wow, I can't believe there isn't a direct API for this - 'runas' will invoke the UAC and ask - for permission before installing the shell extension. note the filepath arg has to be quoted } - procedure CheckRegisterServer; - var - hRegKey: HKEY; - sei: TSHELLEXECUTEINFO; - szBuf: array[0..MAX_PATH*2] of Char; - szFileName: array[0..MAX_PATH] of Char; - begin - if ERROR_SUCCESS = RegOpenKeyEx(HKEY_CLASSES_ROOT, 'miranda.shlext', 0, KEY_READ, hRegKey) then - begin - RegCloseKey(hRegKey); - end else begin - if VistaOrLater then - begin - MessageBox(0, 'Shell context menus requires your permission to register with Windows Explorer (one time only).', - 'Miranda IM - Shell context menus (shlext.dll)', MB_OK or MB_ICONINFORMATION); - // /s = silent - GetModuleFileName(System.hInstance, szFileName, sizeof(szFileName)); - wsprintfs(szBuf, '/s "%s"', szFileName); - ZeroMemory(@sei, sizeof(sei)); - sei.cbSize := sizeof(sei); - sei.lpVerb := 'runas'; - sei.lpFile := 'regsvr32'; - sei.lpParameters := szBuf; - ShellExecuteEx(sei); - end; - end; - end; - -initialization -begin - FillChar(dllpublic, sizeof(dllpublic), 0); - IsMultiThread := True; - VistaOrLater := GetProcAddress(GetModuleHandle('kernel32'), 'GetProductInfo') <> nil; -end; - + { close the map file }
+ CloseHandle(hMap);
+ end; { if }
+ //
+end;
+
+function ThreadServer(hMainThread: Pointer): Cardinal;
+{$IFDEF FPC}
+stdcall;
+{$ENDIF}
+var
+ hEvent: THandle;
+begin
+ Thread_Push(0,0);
+ hEvent := CreateEvent(nil, False, False, PChar(CreateProcessUID(GetCurrentProcessId())));
+ while True do
+ begin
+ Result := WaitForSingleObjectEx(hEvent, INFINITE, True);
+ if Result = WAIT_OBJECT_0 then
+ begin
+ QueueUserAPC(@ipcService, THandle(hMainThread), 0);
+ end; // if
+ if CallService(MS_SYSTEM_TERMINATED, 0, 0) = 1 then
+ break;
+ end; // while
+ CloseHandle(hEvent);
+ CloseHandle(THandle(hMainThread));
+ Thread_Pop();
+ ExitThread(0);
+end;
+
+procedure InvokeThreadServer;
+var
+{$IFDEF FPC}
+ tid: LongWord;
+{$ELSE}
+ tid: Cardinal;
+{$ENDIF}
+var
+ hMainThread: THandle;
+begin
+ hMainThread := 0;
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), @hMainThread,
+ THREAD_SET_CONTEXT, False, 0);
+ if hMainThread <> 0 then
+ begin
+{$IFDEF FPC}
+ CloseHandle(CreateThread(nil, 0, @ThreadServer, Pointer(hMainThread), 0, tid));
+{$ELSE}
+ CloseHandle(BeginThread(nil, 0, @ThreadServer, Pointer(hMainThread), 0, tid));
+{$ENDIF}
+ end; // if
+end;
+
+{ exported functions }
+
+function DllGetClassObject(const CLSID: TCLSID; const IID: TIID; var Obj): HResult; stdcall;
+begin
+ Pointer(Obj) := nil;
+ Result := CLASS_E_CLASSNOTAVAILABLE;
+ if (IsEqualCLSID(CLSID, CLSID_ISHLCOM)) and (IsEqualIID(IID, IID_IClassFactory)) and
+ (FindWindow(MirandaName, nil) <> 0) then
+ begin
+ Pointer(Obj) := TClassFactoryRec_Create;
+ Result := S_OK;
+ end; // if
+end;
+
+function DllCanUnloadNow: HResult;
+begin
+ if ((dllpublic.FactoryCount = 0) and (dllpublic.ObjectCount = 0)) then
+ begin
+ Result := S_OK;
+ end
+ else
+ begin
+ Result := S_FALSE;
+ end; // if
+end;
+
+{ helper functions }
+
+type
+
+ PSHELLEXECUTEINFO = ^TSHELLEXECUTEINFO;
+
+ TSHELLEXECUTEINFO = record
+ cbSize: DWORD;
+ fMask: LongInt;
+ hwnd: THandle;
+ lpVerb: PChar;
+ lpFile: PChar;
+ lpParameters: PChar;
+ lpDirectory: PChar;
+ nShow: Integer;
+ hInstApp: THandle;
+ lpIDLIst: Pointer;
+ lpClass: PChar;
+ HKEY: THandle;
+ dwHotkey: DWORD;
+ HICON: THandle; // is union
+ hProcess: THandle;
+ end;
+
+function ShellExecuteEx(var se: TSHELLEXECUTEINFO): Boolean; stdcall;
+ external 'shell32.dll' name 'ShellExecuteExA';
+
+function wsprintfs(lpOut, lpFmt: PChar; args: PChar): Integer; cdecl;
+ external 'user32.dll' name 'wsprintfA';
+
+function RemoveCOMRegistryEntries: HResult;
+var
+ hRootKey: HKEY;
+begin
+ if RegOpenKeyEx(HKEY_CLASSES_ROOT, 'miranda.shlext', 0, KEY_READ, hRootKey) = ERROR_SUCCESS
+ then
+ begin
+ (* need to delete the subkey before the parent key is deleted under NT/2000/XP *)
+ RegDeleteKey(hRootKey, 'CLSID');
+ (* close the key *)
+ RegCloseKey(hRootKey);
+ (* delete it *)
+ if RegDeleteKey(HKEY_CLASSES_ROOT, 'miranda.shlext') <> ERROR_SUCCESS then
+ begin
+ MessageBox(0,
+ 'Unable to delete registry key for "shlext COM", this key may already be deleted or you may need admin rights.',
+ 'Problem', MB_ICONERROR);
+ end; // if
+ end; // if
+ if RegOpenKeyEx(HKEY_CLASSES_ROOT, '\*\shellex\ContextMenuHandlers', 0, KEY_ALL_ACCESS,
+ hRootKey) = ERROR_SUCCESS then
+ begin
+ if RegDeleteKey(hRootKey, 'miranda.shlext') <> ERROR_SUCCESS then
+ begin
+ MessageBox(0,
+ 'Unable to delete registry key for "File context menu handlers", this key may already be deleted or you may need admin rights.',
+ 'Problem', MB_ICONERROR);
+ end; // if
+ RegCloseKey(hRootKey);
+ end; // if
+ if RegOpenKeyEx(HKEY_CLASSES_ROOT, 'Directory\shellex\ContextMenuHandlers', 0, KEY_ALL_ACCESS,
+ hRootKey) = ERROR_SUCCESS then
+ begin
+ if RegDeleteKey(hRootKey, 'miranda.shlext') <> ERROR_SUCCESS then
+ begin
+ MessageBox(0,
+ 'Unable to delete registry key for "Directory context menu handlers", this key may already be deleted or you may need admin rights.',
+ 'Problem', MB_ICONERROR);
+ end; // if
+ RegCloseKey(hRootKey);
+ end; // if
+ if ERROR_SUCCESS = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ 'Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved', 0, KEY_ALL_ACCESS,
+ hRootKey) then
+ begin
+ if RegDeleteValue(hRootKey, '{72013A26-A94C-11d6-8540-A5E62932711D}') <> ERROR_SUCCESS then
+ begin
+ MessageBox(0,
+ 'Unable to delete registry entry for "Approved context menu handlers", this key may already be deleted or you may need admin rights.',
+ 'Problem', MB_ICONERROR);
+ end; // if
+ RegCloseKey(hRootKey);
+ end; // if
+ Result := S_OK;
+end;
+
+{ called by the options code to remove COM entries, and before that, get permission, if required.
+}
+
+procedure CheckUnregisterServer;
+var
+ sei: TSHELLEXECUTEINFO;
+ szBuf: array [0 .. MAX_PATH * 2] of Char;
+ szFileName: array [0 .. MAX_PATH] of Char;
+begin
+ if not VistaOrLater then
+ begin
+ RemoveCOMRegistryEntries();
+ Exit;
+ end;
+ // launches regsvr to remove the dll under admin.
+ GetModuleFileName(System.hInstance, szFileName, sizeof(szFileName));
+ wsprintfs(szBuf, '/s /u "%s"', szFileName);
+ ZeroMemory(@sei, sizeof(sei));
+ sei.cbSize := sizeof(sei);
+ sei.lpVerb := 'runas';
+ sei.lpFile := 'regsvr32';
+ sei.lpParameters := szBuf;
+ ShellExecuteEx(sei);
+ Sleep(1000);
+ RemoveCOMRegistryEntries();
+end;
+
+{ Wow, I can't believe there isn't a direct API for this - 'runas' will invoke the UAC and ask
+ for permission before installing the shell extension. note the filepath arg has to be quoted }
+procedure CheckRegisterServer;
+var
+ hRegKey: HKEY;
+ sei: TSHELLEXECUTEINFO;
+ szBuf: array [0 .. MAX_PATH * 2] of Char;
+ szFileName: array [0 .. MAX_PATH] of Char;
+begin
+ if ERROR_SUCCESS = RegOpenKeyEx(HKEY_CLASSES_ROOT, 'miranda.shlext', 0, KEY_READ, hRegKey)
+ then
+ begin
+ RegCloseKey(hRegKey);
+ end
+ else
+ begin
+ if VistaOrLater then
+ begin
+ MessageBox(0,
+ 'Shell context menus requires your permission to register with Windows Explorer (one time only).',
+ 'Miranda IM - Shell context menus (shlext.dll)', MB_OK or MB_ICONINFORMATION);
+ // /s = silent
+ GetModuleFileName(System.hInstance, szFileName, sizeof(szFileName));
+ wsprintfs(szBuf, '/s "%s"', szFileName);
+ ZeroMemory(@sei, sizeof(sei));
+ sei.cbSize := sizeof(sei);
+ sei.lpVerb := 'runas';
+ sei.lpFile := 'regsvr32';
+ sei.lpParameters := szBuf;
+ ShellExecuteEx(sei);
+ end;
+ end;
+end;
+
+initialization
+
+begin
+ FillChar(dllpublic, sizeof(dllpublic), 0);
+ IsMultiThread := True;
+ VistaOrLater := GetProcAddress(GetModuleHandle('kernel32'), 'GetProductInfo') <> nil;
+end;
+
end. - diff --git a/plugins/ShlExt/shlext.dpr b/plugins/ShlExt/shlext.dpr index eb772e98a8..2c8c3f0c2d 100644 --- a/plugins/ShlExt/shlext.dpr +++ b/plugins/ShlExt/shlext.dpr @@ -1,379 +1,411 @@ {$IFDEF FPC} - {$PACKRECORDS 4} - {$MODE Delphi} - {$ASMMODE intel} - {$INLINE ON} - {$MACRO ON} - {$APPTYPE GUI}
- {$IMAGEBASE $49ac0000} -{$ELSE} - {$IMAGEBASE $49ac0000} // this is ignored with FPC, must be set via the command line -{$ENDIF} - -library shlext; -uses - - Windows, shlcom, shlipc, m_globaldefs; - - // use the registry to store the COM information needed by the shell - - function DllRegisterServer: HResult; stdcall; - var - szData: PChar; - hRegKey: HKEY; - begin - - {$IFDEF INSTALLER_REGISTER} - Result := S_OK; - {$ELSE} - // progID - szData := 'shlext (1.0.6.6) - shell context menu support for Miranda v0.3.0.0+'; - if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT, 'miranda.shlext', REG_SZ, szData, Length(szData)) then - begin - // CLSID related to ProgID - szData := '{72013A26-A94C-11d6-8540-A5E62932711D}'; - if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT, 'miranda.shlext\CLSID', REG_SZ, szData, Length(szData)) then - begin - // CLSID link back to progID - szData := 'miranda.shlext'; - if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT, 'CLSID\{72013A26-A94C-11d6-8540-A5E62932711D}', REG_SZ, szData, Length(szData)) then - begin - // CLSID link back to ProgID under \ProgID again? - szData := 'miranda.shlext'; - if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT, 'CLSID\{72013A26-A94C-11d6-8540-A5E62932711D}\ProgID', REG_SZ, szData, Length(szData)) then - begin - GetMem(szData, MAX_PATH); - GetModuleFileName(hInstance, szData, MAX_PATH-1); - Result := RegSetValue(HKEY_CLASSES_ROOT, 'CLSID\{72013A26-A94C-11d6-8540-A5E62932711D}\InprocServer32', REG_SZ, szData, Length(szData)); - FreeMem(szData); - if Result = ERROR_SUCCESS then - begin - // have to add threading model - szData := 'CLSID\{72013A26-A94C-11d6-8540-A5E62932711D}\InprocServer32'; - Result := RegCreateKeyEx(HKEY_CLASSES_ROOT, szData, 0, nil, 0, KEY_SET_VALUE or KEY_CREATE_SUB_KEY, nil, hRegKey, nil); - if Result = ERROR_SUCCESS then - begin - szData := 'Apartment'; - RegSetValueEx(hRegKey, 'ThreadingModel', 0, REG_SZ, PByte(szData), Length(szData)+1); - RegCloseKey(hRegKey); - // write which file types to show under - szData := '{72013A26-A94C-11d6-8540-A5E62932711D}'; - // note that *\ should use AllFilesystemObjects for 4.71+ - if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT, '*\shellex\ContextMenuHandlers\miranda.shlext', REG_SZ, szData, Length(szData)) then - begin - // don't support directories - if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT, 'Directory\shellex\ContextMenuHandlers\miranda.shlext', REG_SZ, szData, Length(szData)) then - begin - Result := S_OK; - // have to add to the approved list under NT/2000/XP with {CLSID}="<description>" - szData := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved'; - Result := RegCreateKeyEx(HKEY_LOCAL_MACHINE, szData, 0, nil, 0, KEY_SET_VALUE or KEY_CREATE_SUB_KEY, nil, hRegKey, nil); - if Result = ERROR_SUCCESS then - begin - szData := 'shlext (1.0.6.6) - context menu support for Miranda v0.3.0.0+'; - RegSetValueEx(hRegKey, '{72013A26-A94C-11d6-8540-A5E62932711D}', 0, REG_SZ, PByte(szData), Length(szData)+1); - RegCloseKey(hRegKey); - end; //if - end else Result := E_FAIL; - end else Result := E_FAIL; - end else Result := E_FAIL; - end else Result := E_FAIL; - end else Result := E_FAIL; - end else Result := E_FAIL; - end else Result := E_FAIL; - end else Result := E_FAIL; - // - {$ENDIF} - - end; - - function DllUnregisterServer: HResult; stdcall; - begin - Result := RemoveCOMRegistryEntries(); - end; - - // - miranda section ---- - - {$include m_options.inc} - {$include m_system.inc} - {$include m_database.inc} - {$include m_file.inc} - {$include m_langpack.inc} - {$include m_helpers.inc}
- {$include m_v8.inc} - -const - - COMREG_UNKNOWN = $00000000; - COMREG_OK = $00000001; - COMREG_APPROVED = $00000002; - - function IsCOMRegistered: Integer; - var - hRegKey: HKEY; - lpType: Integer; - begin - Result := 0; - // these arent the BEST checks in the world - if ERROR_SUCCESS = RegOpenKeyEx(HKEY_CLASSES_ROOT, 'miranda.shlext', 0, KEY_READ, hRegKey) then - begin - Result := Result or COMREG_OK; - RegCloseKey(hRegKey); - end; //if - lpType := REG_SZ; - if ERROR_SUCCESS = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved', 0, KEY_READ, hRegKey) then - begin - if ERROR_SUCCESS = RegQueryValueEx(hRegKey, '{72013A26-A94C-11d6-8540-A5E62932711D}', nil, @lpType, nil, nil) then - begin - Result := Result or COMREG_APPROVED; - end; //if - RegCloseKey(hRegKey); - end; // if - end; - - procedure AutoSize(hwnd: THandle); - var - szBuf: array[0..MAX_PATH] of Char; - DC: HDC; - tS: TSize; - i: Integer; - hFont, hOldFont: THandle; - begin - DC := GetDC(hwnd); - hFont := GetStockObject(DEFAULT_GUI_FONT); - hOldFont := SelectObject(DC, hFont); - i := GetWindowText(hwnd, szBuf, MAX_PATH); - GetTextExtentPoint32(DC, szBuf, i, tS); - SelectObject(DC, hOldFont); - DeleteObject(hFont); - ReleaseDC(hwnd, DC); - SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, tS.cx + 10, tS.cy, SWP_NOMOVE or SWP_FRAMECHANGED); - end;
- - function OptDialogProc(hwndDlg: THandle; wMsg: Integer; wParam: WPARAM; lParam: LPARAM): BOOL; stdcall; - // don't wanna bring in CommCtrl just for a few constants - const - {$IFNDEF FPC} - WM_INITDIALOG = $0110; - WM_COMMAND = $0111; - WM_USER = $0400; - WM_NOTIFY = $004E; - {$ENDIF} - { propsheet notifications/msessages } - //PSN_APPLY = (-200) - 2; - PSM_CHANGED = WM_USER + 104; - { button styles } - BCM_SETSHIELD = ({BCM_FIRST}$1600 + $000C); - { hotkey } - // bring in the IDC's and storage key names - {$define SHL_IDC} - {$define SHL_KEYS} - {$include shlc.inc} - {$undef SHL_KEYS} - {$undef SHL_IDC} - const - COM_OKSTR: array[Boolean] of PChar = ( - 'Problem, registration missing/deleted.', - 'Successfully created shell registration.' - ); - COM_APPROVEDSTR: array[Boolean] of PChar = ( - 'Not Approved', - 'Approved' - ); - var - comReg: Integer; - iCheck: Integer; - szBuf: array[0..MAX_PATH] of Char; - cgs: TDBCONTACTGETSETTING; - begin - Result := wMsg = WM_INITDIALOG; - case wMsg of
- WM_NOTIFY:
+{$PACKRECORDS 4}
+{$MODE Delphi}
+{$ASMMODE intel}
+{$INLINE ON}
+{$MACRO ON}
+{$APPTYPE GUI}
+{$IMAGEBASE $49ac0000}
+{$ELSE}
+{$IMAGEBASE $49ac0000} // this is ignored with FPC, must be set via the command line
+{$ENDIF}
+library shlext;
+
+uses
+
+ Windows, shlcom, shlipc, m_api;
+
+// use the registry to store the COM information needed by the shell
+
+function DllRegisterServer: HResult; stdcall;
+var
+ szData: PChar;
+ hRegKey: HKEY;
+begin
+
+{$IFDEF INSTALLER_REGISTER}
+ Result := S_OK;
+{$ELSE}
+ // progID
+ szData := 'shlext (1.0.6.6) - shell context menu support for Miranda v0.3.0.0+';
+ if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT, 'miranda.shlext', REG_SZ, szData,
+ Length(szData)) then
+ begin
+ // CLSID related to ProgID
+ szData := '{72013A26-A94C-11d6-8540-A5E62932711D}';
+ if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT, 'miranda.shlext\CLSID', REG_SZ, szData,
+ Length(szData)) then
+ begin
+ // CLSID link back to progID
+ szData := 'miranda.shlext';
+ if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT,
+ 'CLSID\{72013A26-A94C-11d6-8540-A5E62932711D}', REG_SZ, szData, Length(szData)) then
+ begin
+ // CLSID link back to ProgID under \ProgID again?
+ szData := 'miranda.shlext';
+ if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT,
+ 'CLSID\{72013A26-A94C-11d6-8540-A5E62932711D}\ProgID', REG_SZ, szData, Length(szData))
+ then
+ begin
+ GetMem(szData, MAX_PATH);
+ GetModuleFileName(hInstance, szData, MAX_PATH - 1);
+ Result := RegSetValue(HKEY_CLASSES_ROOT,
+ 'CLSID\{72013A26-A94C-11d6-8540-A5E62932711D}\InprocServer32', REG_SZ, szData,
+ Length(szData));
+ FreeMem(szData);
+ if Result = ERROR_SUCCESS then
+ begin
+ // have to add threading model
+ szData := 'CLSID\{72013A26-A94C-11d6-8540-A5E62932711D}\InprocServer32';
+ Result := RegCreateKeyEx(HKEY_CLASSES_ROOT, szData, 0, nil, 0,
+ KEY_SET_VALUE or KEY_CREATE_SUB_KEY, nil, hRegKey, nil);
+ if Result = ERROR_SUCCESS then
begin
- {* FP 2.2.2 seems to have a bug, 'Code' is supposed to be signed
- but isn't signed, so when comparing -202 (=PSN_APPLY) It doesn't work
- so here, -202 is converted into hex, what you are looking at is the
- code == PSN_APPLY check. *}
- if $FFFFFF36 = pNMHDR(lParam)^.code then
+ szData := 'Apartment';
+ RegSetValueEx(hRegKey, 'ThreadingModel', 0, REG_SZ, PByte(szData),
+ Length(szData) + 1);
+ RegCloseKey(hRegKey);
+ // write which file types to show under
+ szData := '{72013A26-A94C-11d6-8540-A5E62932711D}';
+ // note that *\ should use AllFilesystemObjects for 4.71+
+ if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT,
+ '*\shellex\ContextMenuHandlers\miranda.shlext', REG_SZ, szData, Length(szData))
+ then
+ begin
+ // don't support directories
+ if ERROR_SUCCESS = RegSetValue(HKEY_CLASSES_ROOT,
+ 'Directory\shellex\ContextMenuHandlers\miranda.shlext', REG_SZ, szData,
+ Length(szData)) then
begin
- DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_UseGroups, IsDlgButtonChecked(hwndDlg, IDC_USEGROUPS));
- DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_UseCListSetting, IsDlgButtonChecked(hwndDlg, IDC_CLISTGROUPS));
- DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoProfile, IsDlgButtonChecked(hwndDlg, IDC_NOPROF));
- DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_UseHITContacts, IsDlgButtonChecked(hwndDlg, IDC_SHOWFULL));
- DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_UseHIT2Contacts, IsDlgButtonChecked(hwndDlg, IDC_SHOWINVISIBLES));
- DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoIcons, IsDlgButtonChecked(hwndDlg, IDC_USEOWNERDRAW));
- DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoOffline, IsDlgButtonChecked(hwndDlg, IDC_HIDEOFFLINE));
- end; //if
- end; - WM_INITDIALOG: - begin - TranslateDialogDefault(hwndDlg); - comReg := IsCOMRegistered(); - FillChar(szBuf, MAX_PATH, 0); - lstrcat(szBuf, Translate(COM_OKSTR[comReg and COMREG_OK = COMREG_OK])); - lstrcat(szBuf, ' ('); - lstrcat(szBuf, Translate(COM_APPROVEDSTR[comReg and COMREG_APPROVED = COMREG_APPROVED])); - lstrcat(szBuf, ')'); - SetWindowText(GetDlgItem(hwndDlg, IDC_STATUS), szBuf); - // auto size the static windows to fit their text - // they're rendering in a font not selected into the DC. - AutoSize(GetDlgItem(hwndDlg, IDC_CAPMENUS)); - AutoSize(GetDlgItem(hwndDlg, IDC_CAPSTATUS)); - AutoSize(GetDlgItem(hwndDlg, IDC_CAPSHLSTATUS)); - // show all the options - iCheck := DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseGroups, BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_USEGROUPS, iCheck); - EnableWindow(GetDlgItem(hwndDlg, IDC_CLISTGROUPS), iCheck = BST_CHECKED); - CheckDlgButton(hwndDlg, IDC_CLISTGROUPS, DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseCListSetting, BST_UNCHECKED)); - CheckDlgButton(hwndDlg, IDC_NOPROF, DBGetContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoProfile, BST_UNCHECKED)); - CheckDlgButton(hwndDlg, IDC_SHOWFULL, DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseHITContacts, BST_UNCHECKED)); - CheckDlgButton(hwndDlg, IDC_SHOWINVISIBLES, DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseHIT2Contacts, BST_UNCHECKED)); - CheckDlgButton(hwndDlg, IDC_USEOWNERDRAW, DBGetContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoIcons, BST_UNCHECKED)); - CheckDlgButton(hwndDlg, IDC_HIDEOFFLINE, DBGetContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoOffline, BST_UNCHECKED)); - // give the Remove button a Vista icon - SendMessage(GetDlgItem(hwndDlg, IDC_REMOVE), BCM_SETSHIELD, 0, 1); - end; - WM_COMMAND: - begin - // don't send the changed message if remove is clicked - if LOWORD(wParam) <> IDC_REMOVE then - begin - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - end; //if - case LOWORD(wParam) of - IDC_USEGROUPS: - begin - EnableWindow(GetDlgItem(hwndDlg, IDC_CLISTGROUPS), BST_CHECKED = IsDlgButtonChecked(hwndDlg, IDC_USEGROUPS)); - end; //if - IDC_REMOVE: - begin - if IDYES = MessageBox(0, Translate('Are you sure? this will remove all the settings stored in your database and all registry entries created for shlext to work with Explorer'), Translate('Disable/Remove shlext'), MB_YESNO or MB_ICONQUESTION) then - begin - cgs.szModule := SHLExt_Name; - - cgs.szSetting := SHLExt_UseGroups; - CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs)); - - cgs.szSetting := SHLExt_UseCListSetting; - CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs)); - - cgs.szSetting := SHLExt_UseHITContacts; - CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs)); - - cgs.szSetting := SHLExt_UseHIT2Contacts; - CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs)); - - cgs.szSetting := SHLExt_ShowNoProfile; - CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs)); - - cgs.szSetting := SHLExt_ShowNoIcons; - CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs)); - - cgs.szSetting := SHLExt_ShowNoOffline; - CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs)); - - (* remove from Explorer *) - //DllUnregisterServer(); - CheckUnregisterServer(); - (* show all the settings have gone... *) - SendMessage(hwndDlg, WM_INITDIALOG, 0, 0); - end; //if - end; //if - end; //case - // LOWORD(wParam) == IDC_* - end;{outercase} - end; //case - end; - - function InitialiseOptionPages(wParam: WPARAM; lParam: LPARAM): int; cdecl; - const - IDD_SHLOPTS = 101; - var - optDialog: TOPTIONSDIALOGPAGE; - begin - Result := 0; - FillChar(optDialog, sizeof(TOPTIONSDIALOGPAGE), 0); - optDialog.cbSize := sizeof(TOPTIONSDIALOGPAGE); - optDialog.flags := ODPF_BOLDGROUPS; - optDialog.groupPosition := 0; - optDialog.pszGroup := 'Plugins'; - optDialog.position := -1066; - optDialog.pszTitle := Translate('Shell context menus'); - optDialog.pszTemplate := MAKEINTRESOURCE(IDD_SHLOPTS); - {$ifdef VER140} - optDialog.hInstance := HInstance; - {$else} - optDialog.hInstance := System.hInstance; - {$endif} - optDialog.pfnDlgProc := @OptDialogProc; - PluginLink^.CallService(MS_OPT_ADDPAGE, wParam, Integer(@optDialog)); - end; - - function MirandaPluginInfoEx(mirandaVersion: DWORD): PPLUGININFOEX; cdecl; - begin - Result := nil; - { only support v0.3.0.0+ } - if PLUGIN_MAKE_VERSION(0,3,0,0) > MirandaVersion then Exit; - { fill in plugininfo } - PLUGININFOEX.cbSize := sizeof(PLUGININFOEX); - PLUGININFOEX.shortName := 'Shell context menus for transfers'; - PLUGININFOEX.version := PLUGIN_MAKE_VERSION(2,0,1,2); - {$ifdef FPC} - PLUGININFOEX.description := 'Click ''n'' send support from Explorer/Common dialogs/Desktop, Right click on a file/folder to be presented with all your Miranda contact lists and then select the profile/contact you want to send to. Built on ' + {$I %DATE%} + ' at ' + {$I %TIME%} + ' with FPC ' + {$I %FPCVERSION%}; - {$else} - PLUGININFOEX.description := ''; - {$endif} - PLUGININFOEX.author := 'egoDust'; - PLUGININFOEX.authorEmail := 'egodust@users.sourceforge.net'; - PLUGININFOEX.copyright := '(c) 2009 Sam Kothari (egoDust)'; - PLUGININFOEX.homePage := 'http://addons.miranda-im.org/details.php?action=viewfile&id=534'; - PLUGININFOEX.isTransient := 0; - PLUGININFOEX.replacesDefaultModule := 0;
- { This UUID is fetched twice }
- CopyMemory(@PLUGININFOEX.uuid, @CLSID_ISHLCOM, sizeof(TMUUID)); - { return info } - Result := @PLUGININFOEX; - end;
-
- function MirandaPluginInterfaces: PMUUID; cdecl;
- const
- ifaces: array[0..1] of TMUUID =
- (
- // same as CLSID_ISHLCOM
- (a: $72013a26; b: $a94c; c: $11d6; d: ($85,$40,$a5,$e6,$29,$32,$71,$1d) ),
-
- // MUUID_LASTPLUGIN
- (a: 0; b: 0; c: 0; d:(0,0,0,0,0,0,0,0) )
- );
- begin
- Result := @ifaces;
- end; - - function Load(link: PPLUGINLINK): int; cdecl; - begin - Result := 0; - PLUGINLINK := Pointer(link); - InvokeThreadServer; - PluginLink^.HookEvent(ME_OPT_INITIALISE, InitialiseOptionPages); - DllRegisterServer(); - CheckRegisterServer(); - //DisableThreadLibraryCalls(System.hInstance); - end; - - function Unload: int; cdecl; - begin - Result := 0; - end; - - {$R shldlgs.res} - - exports - - MirandaPluginInfoEx, MirandaPluginInterfaces, Load, Unload; - - exports - - DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer; - -begin + Result := S_OK;
+ // have to add to the approved list under NT/2000/XP with {CLSID}="<description>"
+ szData := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved';
+ Result := RegCreateKeyEx(HKEY_LOCAL_MACHINE, szData, 0, nil, 0,
+ KEY_SET_VALUE or KEY_CREATE_SUB_KEY, nil, hRegKey, nil);
+ if Result = ERROR_SUCCESS then
+ begin
+ szData := 'shlext (1.0.6.6) - context menu support for Miranda v0.3.0.0+';
+ RegSetValueEx(hRegKey, '{72013A26-A94C-11d6-8540-A5E62932711D}', 0, REG_SZ,
+ PByte(szData), Length(szData) + 1);
+ RegCloseKey(hRegKey);
+ end; // if
+ end
+ else
+ Result := E_FAIL;
+ end
+ else
+ Result := E_FAIL;
+ end
+ else
+ Result := E_FAIL;
+ end
+ else
+ Result := E_FAIL;
+ end
+ else
+ Result := E_FAIL;
+ end
+ else
+ Result := E_FAIL;
+ end
+ else
+ Result := E_FAIL;
+ end
+ else
+ Result := E_FAIL;
+ //
+{$ENDIF}
+end;
+
+function DllUnregisterServer: HResult; stdcall;
+begin
+ Result := RemoveCOMRegistryEntries();
+end;
+
+// - miranda section ----
+
+const
+
+ COMREG_UNKNOWN = $00000000;
+ COMREG_OK = $00000001;
+ COMREG_APPROVED = $00000002;
+
+function IsCOMRegistered: Integer;
+var
+ hRegKey: HKEY;
+ lpType: Integer;
+begin
+ Result := 0;
+ // these arent the BEST checks in the world
+ if ERROR_SUCCESS = RegOpenKeyEx(HKEY_CLASSES_ROOT, 'miranda.shlext', 0, KEY_READ, hRegKey)
+ then
+ begin
+ Result := Result or COMREG_OK;
+ RegCloseKey(hRegKey);
+ end; // if
+ lpType := REG_SZ;
+ if ERROR_SUCCESS = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ 'Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved', 0, KEY_READ, hRegKey)
+ then
+ begin
+ if ERROR_SUCCESS = RegQueryValueEx(hRegKey, '{72013A26-A94C-11d6-8540-A5E62932711D}', nil,
+ @lpType, nil, nil) then
+ begin
+ Result := Result or COMREG_APPROVED;
+ end; // if
+ RegCloseKey(hRegKey);
+ end; // if
+end;
+
+procedure AutoSize(hwnd: THandle);
+var
+ szBuf: array [0 .. MAX_PATH] of Char;
+ DC: HDC;
+ tS: TSize;
+ i: Integer;
+ hFont, hOldFont: THandle;
+begin
+ DC := GetDC(hwnd);
+ hFont := GetStockObject(DEFAULT_GUI_FONT);
+ hOldFont := SelectObject(DC, hFont);
+ i := GetWindowText(hwnd, szBuf, MAX_PATH);
+ GetTextExtentPoint32(DC, szBuf, i, tS);
+ SelectObject(DC, hOldFont);
+ DeleteObject(hFont);
+ ReleaseDC(hwnd, DC);
+ SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, tS.cx + 10, tS.cy, SWP_NOMOVE or SWP_FRAMECHANGED);
+end;
+
+function OptDialogProc(hwndDlg: THandle; wMsg: Integer; wParam: wParam; lParam: lParam)
+ : BOOL; stdcall;
+// don't wanna bring in CommCtrl just for a few constants
+const
+{$IFNDEF FPC}
+ WM_INITDIALOG = $0110;
+ WM_COMMAND = $0111;
+ WM_USER = $0400;
+ WM_NOTIFY = $004E;
+{$ENDIF}
+ { propsheet notifications/msessages }
+ // PSN_APPLY = (-200) - 2;
+ PSM_CHANGED = WM_USER + 104;
+ { button styles }
+ BCM_SETSHIELD = ( { BCM_FIRST } $1600 + $000C);
+ { hotkey }
+ // bring in the IDC's and storage key names
+{$DEFINE SHL_IDC}
+{$DEFINE SHL_KEYS}
+{$INCLUDE shlc.inc}
+{$UNDEF SHL_KEYS}
+{$UNDEF SHL_IDC}
+const
+ COM_OKSTR: array [Boolean] of PChar = ('Problem, registration missing/deleted.',
+ 'Successfully created shell registration.');
+ COM_APPROVEDSTR: array [Boolean] of PChar = ('Not Approved', 'Approved');
+var
+ comReg: Integer;
+ iCheck: Integer;
+ szBuf: array [0 .. MAX_PATH] of Char;
+ cgs: TDBCONTACTGETSETTING;
+begin
+ Result := wMsg = WM_INITDIALOG;
+ case wMsg of
+ WM_NOTIFY:
+ begin
+ { * FP 2.2.2 seems to have a bug, 'Code' is supposed to be signed
+ but isn't signed, so when comparing -202 (=PSN_APPLY) It doesn't work
+ so here, -202 is converted into hex, what you are looking at is the
+ code == PSN_APPLY check. * }
+ if $FFFFFF36 = pNMHDR(lParam)^.code then
+ begin
+ DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_UseGroups,
+ IsDlgButtonChecked(hwndDlg, IDC_USEGROUPS));
+ DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_UseCListSetting,
+ IsDlgButtonChecked(hwndDlg, IDC_CLISTGROUPS));
+ DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoProfile,
+ IsDlgButtonChecked(hwndDlg, IDC_NOPROF));
+ DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_UseHITContacts,
+ IsDlgButtonChecked(hwndDlg, IDC_SHOWFULL));
+ DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_UseHIT2Contacts,
+ IsDlgButtonChecked(hwndDlg, IDC_SHOWINVISIBLES));
+ DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoIcons,
+ IsDlgButtonChecked(hwndDlg, IDC_USEOWNERDRAW));
+ DBWriteContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoOffline,
+ IsDlgButtonChecked(hwndDlg, IDC_HIDEOFFLINE));
+ end; // if
+ end;
+ WM_INITDIALOG:
+ begin
+ TranslateDialogDefault(hwndDlg);
+ comReg := IsCOMRegistered();
+ FillChar(szBuf, MAX_PATH, 0);
+ lstrcat(szBuf, Translate(COM_OKSTR[comReg and COMREG_OK = COMREG_OK]));
+ lstrcat(szBuf, ' (');
+ lstrcat(szBuf, Translate(COM_APPROVEDSTR[comReg and
+ COMREG_APPROVED = COMREG_APPROVED]));
+ lstrcat(szBuf, ')');
+ SetWindowText(GetDlgItem(hwndDlg, IDC_STATUS), szBuf);
+ // auto size the static windows to fit their text
+ // they're rendering in a font not selected into the DC.
+ AutoSize(GetDlgItem(hwndDlg, IDC_CAPMENUS));
+ AutoSize(GetDlgItem(hwndDlg, IDC_CAPSTATUS));
+ AutoSize(GetDlgItem(hwndDlg, IDC_CAPSHLSTATUS));
+ // show all the options
+ iCheck := DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseGroups, BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_USEGROUPS, iCheck);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CLISTGROUPS), iCheck = BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_CLISTGROUPS, DBGetContactSettingByte(0, SHLExt_Name,
+ SHLExt_UseCListSetting, BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_NOPROF, DBGetContactSettingByte(0, SHLExt_Name,
+ SHLExt_ShowNoProfile, BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_SHOWFULL, DBGetContactSettingByte(0, SHLExt_Name,
+ SHLExt_UseHITContacts, BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_SHOWINVISIBLES, DBGetContactSettingByte(0, SHLExt_Name,
+ SHLExt_UseHIT2Contacts, BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_USEOWNERDRAW, DBGetContactSettingByte(0, SHLExt_Name,
+ SHLExt_ShowNoIcons, BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_HIDEOFFLINE, DBGetContactSettingByte(0, SHLExt_Name,
+ SHLExt_ShowNoOffline, BST_UNCHECKED));
+ // give the Remove button a Vista icon
+ SendMessage(GetDlgItem(hwndDlg, IDC_REMOVE), BCM_SETSHIELD, 0, 1);
+ end;
+ WM_COMMAND:
+ begin
+ // don't send the changed message if remove is clicked
+ if LOWORD(wParam) <> IDC_REMOVE then
+ begin
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ end; // if
+ case LOWORD(wParam) of
+ IDC_USEGROUPS:
+ begin
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CLISTGROUPS),
+ BST_CHECKED = IsDlgButtonChecked(hwndDlg, IDC_USEGROUPS));
+ end; // if
+ IDC_REMOVE:
+ begin
+ if IDYES = MessageBox(0,
+ Translate(
+ 'Are you sure? this will remove all the settings stored in your database and all registry entries created for shlext to work with Explorer'),
+ Translate('Disable/Remove shlext'), MB_YESNO or MB_ICONQUESTION) then
+ begin
+ cgs.szModule := SHLExt_Name;
+
+ cgs.szSetting := SHLExt_UseGroups;
+ CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs));
+
+ cgs.szSetting := SHLExt_UseCListSetting;
+ CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs));
+
+ cgs.szSetting := SHLExt_UseHITContacts;
+ CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs));
+
+ cgs.szSetting := SHLExt_UseHIT2Contacts;
+ CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs));
+
+ cgs.szSetting := SHLExt_ShowNoProfile;
+ CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs));
+
+ cgs.szSetting := SHLExt_ShowNoIcons;
+ CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs));
+
+ cgs.szSetting := SHLExt_ShowNoOffline;
+ CallService(MS_DB_CONTACT_DELETESETTING, 0, Integer(@cgs));
+
+ (* remove from Explorer *)
+ // DllUnregisterServer();
+ CheckUnregisterServer();
+ (* show all the settings have gone... *)
+ SendMessage(hwndDlg, WM_INITDIALOG, 0, 0);
+ end; // if
+ end; // if
+ end; // case
+ // LOWORD(wParam) == IDC_*
+ end; { outercase }
+ end; // case
+end;
+
+function InitialiseOptionPages(wParam: wParam; lParam: lParam): int; cdecl;
+const
+ IDD_SHLOPTS = 101;
+var
+ optDialog: TOPTIONSDIALOGPAGE;
+begin
+ Result := 0;
+ FillChar(optDialog, sizeof(TOPTIONSDIALOGPAGE), 0);
+ optDialog.cbSize := sizeof(TOPTIONSDIALOGPAGE);
+ optDialog.flags := ODPF_BOLDGROUPS;
+ optDialog.groupPosition := 0;
+ optDialog.szGroup.a := 'Plugins';
+ optDialog.position := -1066;
+ optDialog.szTitle.a := Translate('Shell context menus');
+ optDialog.pszTemplate := MAKEINTRESOURCE(IDD_SHLOPTS);
+{$IFDEF VER140}
+ optDialog.hInstance := hInstance;
+{$ELSE}
+ optDialog.hInstance := System.hInstance;
+{$ENDIF}
+ optDialog.pfnDlgProc := @OptDialogProc;
+ CallService(MS_OPT_ADDPAGE, wParam, Integer(@optDialog));
+end;
+
+var
+ PLUGININFOEX: TPLUGININFOEX;
+
+function MirandaPluginInfoEx(mirandaVersion: DWORD): PPLUGININFOEX; cdecl;
+begin
+ Result := nil;
+ { only support v0.3.0.0+ }
+ if PLUGIN_MAKE_VERSION(0, 3, 0, 0) > mirandaVersion then
+ Exit;
+ { fill in plugininfo }
+ PLUGININFOEX.cbSize := sizeof(PLUGININFOEX);
+ PLUGININFOEX.shortName := 'Shell context menus for transfers';
+ PLUGININFOEX.version := PLUGIN_MAKE_VERSION(2, 0, 1, 2);
+{$IFDEF FPC}
+ PLUGININFOEX.description :=
+ 'Click ''n'' send support from Explorer/Common dialogs/Desktop, Right click on a file/folder to be presented with all your Miranda contact lists and then select the profile/contact you want to send to. Built on ' +
+ {$I %DATE%} +' at ' + {$I %TIME%} +' with FPC ' + {$I %FPCVERSION%};
+{$ELSE}
+ PLUGININFOEX.description := '';
+{$ENDIF}
+ PLUGININFOEX.author := 'egoDust';
+ PLUGININFOEX.authorEmail := 'egodust@users.sourceforge.net';
+ PLUGININFOEX.copyright := '(c) 2009 Sam Kothari (egoDust)';
+ PLUGININFOEX.homePage := 'http://addons.miranda-im.org/details.php?action=viewfile&id=534';
+ PLUGININFOEX.flags := 0;
+ PLUGININFOEX.replacesDefaultModule := 0;
+ { This UUID is fetched twice }
+ CopyMemory(@PLUGININFOEX.uuid, @CLSID_ISHLCOM, sizeof(TMUUID));
+ { return info }
+ Result := @PLUGININFOEX;
+end;
+
+function Load(): int; cdecl;
+begin
+ Result := 0;
+ InvokeThreadServer;
+ HookEvent(ME_OPT_INITIALISE, InitialiseOptionPages);
+ DllRegisterServer();
+ CheckRegisterServer();
+ // DisableThreadLibraryCalls(System.hInstance);
+end;
+
+function Unload: int; cdecl;
+begin
+ Result := 0;
+end;
+
+{$R shldlgs.res}
+
+exports
+
+ MirandaPluginInfoEx, Load, Unload;
+
+exports
+
+ DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer;
+
+begin
+
end. diff --git a/plugins/ShlExt/shlicons.pas b/plugins/ShlExt/shlicons.pas index a5c2e5d393..ec6a1f4922 100644 --- a/plugins/ShlExt/shlicons.pas +++ b/plugins/ShlExt/shlicons.pas @@ -1,162 +1,170 @@ unit shlicons; - -interface - -uses - - Windows; - -type - - PVTable_IWICBitmap = ^TVTable_IWICBitmap; - TVTable_IWICBitmap = record - { IUnknown } - QueryInterface: Pointer; - AddRef: function(Self: Pointer): Cardinal; stdcall; - Release: function(Self: Pointer): Cardinal; stdcall; - { IWICBitmapSource } - GetSize: function(Self: Pointer; var Width, Height: LongInt): HResult; stdcall; - GetPixelFormat: Pointer; - GetResolution: Pointer; - CopyPalette: Pointer; - CopyPixels: function(Self: Pointer; prc: Pointer; cbStride, cbBufferSize: LongWord; pbBuffer: PByte): HResult; stdcall; - { IWICBitmap } - // .... not used - - end; - - PWICBitmap_Interface = ^TWICBitmap_Interface; - TWICBitmap_Interface = record - ptrVTable: PVTable_IWICBitmap; - end; - - // bare minmum interface to ImagingFactory - - PVTable_ImagingFactory = ^TVTable_ImagingFactory; - TVTable_ImagingFactory = record - { IUnknown } - QueryInterface: Pointer; - AddRef: function(Self: Pointer): Cardinal; stdcall; - Release: function(Self: Pointer): Cardinal; stdcall; - { ImagingFactory } - CreateDecoderFromFilename: Pointer; - CreateDecoderFromStream: Pointer; - CreateDecoderFromFileHandle: Pointer; - CreateComponentInfo: Pointer; - CreateDecoder: Pointer; - CreateEncoder: Pointer; - CreatePalette: Pointer; - CreateFormatConverter: Pointer; - CreateBitmapScaler: Pointer; - CreateBitmapClipper: Pointer; - CreateBitmapFlipRotator: Pointer; - CreateStream: Pointer; - CreateColorContext: Pointer; - CreateColorTransformer: Pointer; - CreateBitmap: Pointer; - CreateBitmapFromSource: Pointer; - CreateBitmapFromSourceRect: Pointer; - CreateBitmapFromMemory: Pointer; - CreateBitmapFromHBITMAP: Pointer; - CreateBitmapFromHICON: function(Self: Pointer; hIcon: Windows.HICON; var foo: Pointer): HResult; stdcall; - { rest ommited } - end; - - PImageFactory_Interface = ^TImageFactory_Interface; - TImageFactory_Interface = record - ptrVTable: PVTable_ImagingFactory; - end; - - function ARGB_GetWorker: PImageFactory_Interface; - - function ARGB_BitmapFromIcon(Factory: PImageFactory_Interface; hdc: Windows.HDC; hIcon: HICON): HBitmap; - -implementation - - {$define SHLCOM} - {$define COM_STRUCTS} - {$define COMAPI} - {$include shlc.inc} - {$undef SHLCOM} - {$undef COM_STRUCTS} - {$undef COMAPI} - - { - The following implementation has been ported from: - - http://web.archive.org/web/20080121112802/http://shellrevealed.com/blogs/shellblog/archive/2007/02/06/Vista-Style-Menus_2C00_-Part-1-_2D00_-Adding-icons-to-standard-menus.aspx - - It uses WIC (Windows Imaging Codec) to convert the given Icon into a bitmap in ARGB format, this is required - by Windows for use as an icon (but in bitmap format), so that Windows draws everything (including theme) - so we don't have to. - - Why didn't they just do this themselves? ... - } - - { - The object returned from this function has to be released using the QI COM interface, don't forget. - Note this function won't work on anything where WIC isn't installed (XP can have it installed, but not by default) - anything less won't work. - } - function ARGB_GetWorker: PImageFactory_Interface; - var - hr: HRESULT; - begin - hr := CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER, IID_WICImagingFactory, Result); - end; - - function ARGB_BitmapFromIcon(Factory: PImageFactory_Interface; hdc: Windows.HDC; hIcon: HICON): HBitmap; - var - bmi: BITMAPINFO; - hr: HRESULT; - bitmap: PWICBitmap_Interface; - cx, cy: LongInt; - pbBuffer: PByte; - hBmp: HBITMAP; - cbStride, cbBuffer: LongInt; - begin - { This code gives an icon to WIC and gets a bitmap object in return, it then creates a DIB section - which is 32bits and the same H*W as the icon. It then asks the bitmap object to copy itself into the DIB } - Result := 0; - ZeroMemory(@bmi, sizeof(bmi)); - bmi.bmiHeader.biSize := sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biPlanes := 1; - bmi.bmiHeader.biCompression := BI_RGB; - - bmi.bmiHeader.biBitCount := 32; - - hr := factory^.ptrVTable^.CreateBitmapFromHICON(factory, hIcon, bitmap); - if hr = S_OK then - begin - hr := bitmap^.ptrVTable^.GetSize(bitmap, cx, cy); - if hr = S_OK then - begin - - bmi.bmiHeader.biWidth := cx; - bmi.bmiHeader.biHeight := -cy; - - hBmp := CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, pbBuffer, 0, 0); - if hBmp <> 0 then - begin - cbStride := cx * sizeof(DWORD); // ARGB = DWORD - cbBuffer := cy * cbStride; - // note: the pbBuffer memory is owned by the DIB and will be freed when the bitmap is released - hr := bitmap^.ptrVTable^.CopyPixels(bitmap, nil, cbStride, cbBuffer, pbBuffer); - if hr = S_OK then - begin - Result := hBmp; - end else begin - // the copy failed, delete the DIB - DeleteObject(hBmp); - end; - end; - end; - // release the bitmap object now - bitmap^.ptrVTable^.Release(bitmap); - bitmap := nil; - end; - - end; - -end -.
\ No newline at end of file +
+interface
+
+uses
+ Windows;
+
+type
+
+ PVTable_IWICBitmap = ^TVTable_IWICBitmap;
+
+ TVTable_IWICBitmap = record
+ { IUnknown }
+ QueryInterface: Pointer;
+ AddRef: function(Self: Pointer): Cardinal; stdcall;
+ Release: function(Self: Pointer): Cardinal; stdcall;
+ { IWICBitmapSource }
+ GetSize: function(Self: Pointer; var Width, Height: LongInt): HResult; stdcall;
+ GetPixelFormat: Pointer;
+ GetResolution: Pointer;
+ CopyPalette: Pointer;
+ CopyPixels: function(Self: Pointer; prc: Pointer; cbStride, cbBufferSize: LongWord;
+ pbBuffer: PByte): HResult; stdcall;
+ { IWICBitmap }
+ // .... not used
+
+ end;
+
+ PWICBitmap_Interface = ^TWICBitmap_Interface;
+
+ TWICBitmap_Interface = record
+ ptrVTable: PVTable_IWICBitmap;
+ end;
+
+ // bare minmum interface to ImagingFactory
+
+ PVTable_ImagingFactory = ^TVTable_ImagingFactory;
+
+ TVTable_ImagingFactory = record
+ { IUnknown }
+ QueryInterface: Pointer;
+ AddRef: function(Self: Pointer): Cardinal; stdcall;
+ Release: function(Self: Pointer): Cardinal; stdcall;
+ { ImagingFactory }
+ CreateDecoderFromFilename: Pointer;
+ CreateDecoderFromStream: Pointer;
+ CreateDecoderFromFileHandle: Pointer;
+ CreateComponentInfo: Pointer;
+ CreateDecoder: Pointer;
+ CreateEncoder: Pointer;
+ CreatePalette: Pointer;
+ CreateFormatConverter: Pointer;
+ CreateBitmapScaler: Pointer;
+ CreateBitmapClipper: Pointer;
+ CreateBitmapFlipRotator: Pointer;
+ CreateStream: Pointer;
+ CreateColorContext: Pointer;
+ CreateColorTransformer: Pointer;
+ CreateBitmap: Pointer;
+ CreateBitmapFromSource: Pointer;
+ CreateBitmapFromSourceRect: Pointer;
+ CreateBitmapFromMemory: Pointer;
+ CreateBitmapFromHBITMAP: Pointer;
+ CreateBitmapFromHICON: function(Self: Pointer; hIcon: Windows.hIcon; var foo: Pointer)
+ : HResult; stdcall;
+ { rest ommited }
+ end;
+
+ PImageFactory_Interface = ^TImageFactory_Interface;
+
+ TImageFactory_Interface = record
+ ptrVTable: PVTable_ImagingFactory;
+ end;
+
+function ARGB_GetWorker: PImageFactory_Interface;
+
+function ARGB_BitmapFromIcon(Factory: PImageFactory_Interface; hdc: Windows.hdc; hIcon: hIcon)
+ : HBitmap;
+
+implementation
+
+{$DEFINE SHLCOM}
+{$DEFINE COM_STRUCTS}
+{$DEFINE COMAPI}
+{$INCLUDE shlc.inc}
+{$UNDEF SHLCOM}
+{$UNDEF COM_STRUCTS}
+{$UNDEF COMAPI}
+{
+ The following implementation has been ported from:
+
+ http://web.archive.org/web/20080121112802/http://shellrevealed.com/blogs/shellblog/archive/2007/02/06/Vista-Style-Menus_2C00_-Part-1-_2D00_-Adding-icons-to-standard-menus.aspx
+
+ It uses WIC (Windows Imaging Codec) to convert the given Icon into a bitmap in ARGB format, this is required
+ by Windows for use as an icon (but in bitmap format), so that Windows draws everything (including theme)
+ so we don't have to.
+
+ Why didn't they just do this themselves? ...
+}
+
+{
+ The object returned from this function has to be released using the QI COM interface, don't forget.
+ Note this function won't work on anything where WIC isn't installed (XP can have it installed, but not by default)
+ anything less won't work.
+}
+function ARGB_GetWorker: PImageFactory_Interface;
+var
+ hr: HResult;
+begin
+ hr := CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER,
+ IID_WICImagingFactory, Result);
+end;
+
+function ARGB_BitmapFromIcon(Factory: PImageFactory_Interface; hdc: Windows.hdc;
+ hIcon: hIcon): HBitmap;
+var
+ bmi: BITMAPINFO;
+ hr: HResult;
+ bitmap: PWICBitmap_Interface;
+ cx, cy: LongInt;
+ pbBuffer: PByte;
+ hBmp: HBitmap;
+ cbStride, cbBuffer: LongInt;
+begin
+ { This code gives an icon to WIC and gets a bitmap object in return, it then creates a DIB section
+ which is 32bits and the same H*W as the icon. It then asks the bitmap object to copy itself into the DIB }
+ Result := 0;
+ ZeroMemory(@bmi, sizeof(bmi));
+ bmi.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biPlanes := 1;
+ bmi.bmiHeader.biCompression := BI_RGB;
+
+ bmi.bmiHeader.biBitCount := 32;
+
+ hr := Factory^.ptrVTable^.CreateBitmapFromHICON(Factory, hIcon, bitmap);
+ if hr = S_OK then
+ begin
+ hr := bitmap^.ptrVTable^.GetSize(bitmap, cx, cy);
+ if hr = S_OK then
+ begin
+
+ bmi.bmiHeader.biWidth := cx;
+ bmi.bmiHeader.biHeight := -cy;
+
+ hBmp := CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, pbBuffer, 0, 0);
+ if hBmp <> 0 then
+ begin
+ cbStride := cx * sizeof(DWORD); // ARGB = DWORD
+ cbBuffer := cy * cbStride;
+ // note: the pbBuffer memory is owned by the DIB and will be freed when the bitmap is released
+ hr := bitmap^.ptrVTable^.CopyPixels(bitmap, nil, cbStride, cbBuffer, pbBuffer);
+ if hr = S_OK then
+ begin
+ Result := hBmp;
+ end
+ else
+ begin
+ // the copy failed, delete the DIB
+ DeleteObject(hBmp);
+ end;
+ end;
+ end;
+ // release the bitmap object now
+ bitmap^.ptrVTable^.Release(bitmap);
+ bitmap := nil;
+ end;
+
+end;
+
+end. diff --git a/plugins/ShlExt/shlipc.pas b/plugins/ShlExt/shlipc.pas index 377a82f294..f2195f8060 100644 --- a/plugins/ShlExt/shlipc.pas +++ b/plugins/ShlExt/shlipc.pas @@ -1,369 +1,396 @@ unit shlIPC; - -interface - -uses - - m_globaldefs, Windows; - -const - - REPLY_FAIL = $88888888; - REPLY_OK = $00000000; - - REQUEST_ICONS = 1; - REQUEST_GROUPS = (REQUEST_ICONS) shl 1; - REQUEST_CONTACTS = (REQUEST_GROUPS) shl 1; - REQUEST_XFRFILES = (REQUEST_CONTACTS) shl 1; - REQUEST_NEWICONS = (REQUEST_XFRFILES) shl 1;
- REQUEST_CLEARMRU = (REQUEST_NEWICONS) shl 1; - - ICONS_NOTIMPL = $00000008; - GROUPS_NOTIMPL = $00000080; - CONTACTS_NOTIMPL = $00000800; - - STATUS_PROFILENAME = 2;
- - - // there maybe more than one reason why any request type wasn't returned - -type - - { this can be a group entry, if it is, hContact = <index> - the string contains the full group path } - - PSlotIPC = ^TSlotIPC; - TSlotIPC = packed record - cbSize: Byte; - fType: int; // a REQUEST_* type - Next: PSlotIPC; - hContact: THandle; - hProto: Cardinal; // hash of the protocol the user is on - hGroup: Cardinal; // hash of the entire path (not defined for REQUEST_GROUPS slots) - Status: Word; // only used for contacts -- can be STATUS_PROFILENAME -- but that is because returning the profile name is optional
- MRU: Byte; // if set, contact has been recently used - cbStrSection: int; - end; - - // if the slot contains a nickname, after the NULL, there is another NULL or a group path string - - PSlotProtoIcons = ^TSlotProtoIcons; - TSlotProtoIcons = packed record - pid: Cardinal; // pid of Miranda this protocol was on - hProto: Cardinal; // hash of the protocol - hIcons: array[0..9] of HICON; // each status in order of ID_STATUS_* - hBitmaps: array[0..9] of HBITMAP; // each status "icon" as a bitmap - end; - TSlotProtoIconsArray=array[0..0] of TSlotProtoIcons; - // the process space the thread is running in WILL use a different mapping - // address than the client's process space, addresses need to be adjusted - // to the client's process space.. this is done by the following means : - - // - // new_addr := (old_address - serverbase) + client base - // - // this isn't the best of solutions, the link list should be a variant array - // without random access, which would mean each element's different - // size would need to be computed each time it is accessed or read past - - PHeaderIPC = ^THeaderIPC; - THeaderIPC = record - cbSize: Cardinal; - dwVersion: Cardinal; - pServerBaseAddress: Pointer; - pClientBaseAddress: Pointer; - fRequests: Cardinal; - dwFlags: Cardinal; - Slots: Cardinal; - Param: Cardinal; - SignalEventName: array[0..63] of Char;
- // Translate() won't work via Explorer - MirandaName: array[0..63] of Char;
- MRUMenuName: array[0..63] of Char; // for the MRU menu itself
- ClearEntries: array[0..63] of Char; // for the "clear entries" - IconsBegin: PSlotIPC; - ContactsBegin: PSlotIPC; - GroupsBegin: PSlotIPC; - NewIconsBegin: PSlotIPC; - // start of an flat memory stack, which is referenced as a linked list - DataSize: int; - DataPtr: PSlotIPC; - DataPtrEnd: PSlotIPC; - DataFramePtr: Pointer; - end; - - const HIPC_NOICONS = 1; - - procedure ipcPrepareRequests(ipcPacketSize: int; pipch: PHeaderIPC; fRequests: Cardinal); - function ipcSendRequest(hSignal, hWaitFor: THandle; pipch: PHeaderIPC; dwTimeoutMsecs: DWORD): Cardinal; - function ipcAlloc(pipch: PHeaderIPC; nSize: Integer): PSlotIPC; - procedure ipcFixupAddresses(FromServer: LongBool; pipch: PHeaderIPC); - -type - - TStrTokRec = record - szStr: PChar; - szSet: set of Char; - // need a delimiter after the token too?, e.g. FOO^BAR^ if FOO^BAR - // is the string then only FOO^ is returned, could cause infinite loops - // if the condition isn't accounted for thou. - bSetTerminator: Boolean; - end; - - function StrTok(var strr: TStrTokRec): PChar; - -type - - PGroupNode = ^TGroupNode; - TGroupNode = record - Left, Right, _prev, _next: PGroupNode; - Depth: Cardinal; - Hash: Cardinal; // hash of the group name alone - szGroup: PChar; - cchGroup: Integer; - hMenu: THandle; - hMenuGroupID: Integer; - dwItems: Cardinal; - end; - - PGroupNodeList = ^TGroupNodeList; - TGroupNodeList = record - First, Last: PGroupNode; - end; - - function AllocGroupNode(list: PGroupNodeList; Root: PGroupNode; Depth: Integer): PGroupNode; - function FindGroupNode(P: PGroupNode; const Hash, Depth: Integer): PGroupNode; - -type - - // a contact can never be a submenu too. - TSlotDrawType = (dtEntry, dtGroup, dtContact, dtCommand); - TSlotDrawTypes = set of TSlotDrawType; - - PMenuDrawInfo = ^TMenuDrawInfo;
-
- TMenuCommandCallback = function(
- pipch: PHeaderIPC; // IPC header info, already mapped
- hWorkThreadEvent: THandle; // event object being waited on on miranda thread
- hAckEvent: THandle; // ack event object that has been created
- psd: PMenuDrawInfo // command/draw info
- ): Integer; stdcall;
- - TMenuDrawInfo = record - szText: PChar; - szProfile: PChar; - cch: Integer; - wID: Integer; // should be the same as the menu item's ID - fTypes: TSlotDrawTypes; - hContact: THandle; - hStatusIcon: THandle; // HICON from Self^.ProtoIcons[index].hIcons[status]; Do not DestroyIcon() - hStatusBitmap: THandle; // HBITMAP, don't free. - pid: Integer;
- MenuCommandCallback: TMenuCommandCallback; // dtCommand must be set also. +
+interface
+
+uses
+
+ m_api, Windows;
+
+const
+
+ REPLY_FAIL = $88888888;
+ REPLY_OK = $00000000;
+
+ REQUEST_ICONS = 1;
+ REQUEST_GROUPS = (REQUEST_ICONS) shl 1;
+ REQUEST_CONTACTS = (REQUEST_GROUPS) shl 1;
+ REQUEST_XFRFILES = (REQUEST_CONTACTS) shl 1;
+ REQUEST_NEWICONS = (REQUEST_XFRFILES) shl 1;
+ REQUEST_CLEARMRU = (REQUEST_NEWICONS) shl 1;
+
+ ICONS_NOTIMPL = $00000008;
+ GROUPS_NOTIMPL = $00000080;
+ CONTACTS_NOTIMPL = $00000800;
+
+ STATUS_PROFILENAME = 2;
+
+
+ // there maybe more than one reason why any request type wasn't returned
+
+type
+
+ { this can be a group entry, if it is, hContact = <index>
+ the string contains the full group path }
+
+ PSlotIPC = ^TSlotIPC;
+
+ TSlotIPC = packed record
+ cbSize: Byte;
+ fType: int; // a REQUEST_* type
+ Next: PSlotIPC;
+ hContact: THandle;
+ hProto: Cardinal; // hash of the protocol the user is on
+ hGroup: Cardinal; // hash of the entire path (not defined for REQUEST_GROUPS slots)
+ Status: Word;
+ // only used for contacts -- can be STATUS_PROFILENAME -- but that is because returning the profile name is optional
+ MRU: Byte; // if set, contact has been recently used
+ cbStrSection: int;
+ end;
+
+ // if the slot contains a nickname, after the NULL, there is another NULL or a group path string
+
+ PSlotProtoIcons = ^TSlotProtoIcons;
+
+ TSlotProtoIcons = packed record
+ pid: Cardinal; // pid of Miranda this protocol was on
+ hProto: Cardinal; // hash of the protocol
+ hIcons: array [0 .. 9] of HICON; // each status in order of ID_STATUS_*
+ hBitmaps: array [0 .. 9] of HBITMAP; // each status "icon" as a bitmap
+ end;
+
+ TSlotProtoIconsArray = array [0 .. 0] of TSlotProtoIcons;
+ // the process space the thread is running in WILL use a different mapping
+ // address than the client's process space, addresses need to be adjusted
+ // to the client's process space.. this is done by the following means :
+
+ //
+ // new_addr := (old_address - serverbase) + client base
+ //
+ // this isn't the best of solutions, the link list should be a variant array
+ // without random access, which would mean each element's different
+ // size would need to be computed each time it is accessed or read past
+
+ PHeaderIPC = ^THeaderIPC;
+
+ THeaderIPC = record
+ cbSize: Cardinal;
+ dwVersion: Cardinal;
+ pServerBaseAddress: Pointer;
+ pClientBaseAddress: Pointer;
+ fRequests: Cardinal;
+ dwFlags: Cardinal;
+ Slots: Cardinal;
+ Param: Cardinal;
+ SignalEventName: array [0 .. 63] of Char;
+ // Translate() won't work via Explorer
+ MirandaName: array [0 .. 63] of Char;
+ MRUMenuName: array [0 .. 63] of Char; // for the MRU menu itself
+ ClearEntries: array [0 .. 63] of Char; // for the "clear entries"
+ IconsBegin: PSlotIPC;
+ ContactsBegin: PSlotIPC;
+ GroupsBegin: PSlotIPC;
+ NewIconsBegin: PSlotIPC;
+ // start of an flat memory stack, which is referenced as a linked list
+ DataSize: int;
+ DataPtr: PSlotIPC;
+ DataPtrEnd: PSlotIPC;
+ DataFramePtr: Pointer;
+ end;
+
+const
+ HIPC_NOICONS = 1;
+
+procedure ipcPrepareRequests(ipcPacketSize: int; pipch: PHeaderIPC; fRequests: Cardinal);
+function ipcSendRequest(hSignal, hWaitFor: THandle; pipch: PHeaderIPC; dwTimeoutMsecs: DWORD)
+ : Cardinal;
+function ipcAlloc(pipch: PHeaderIPC; nSize: Integer): PSlotIPC;
+procedure ipcFixupAddresses(FromServer: LongBool; pipch: PHeaderIPC);
+
+type
+
+ TStrTokRec = record
+ szStr: PChar;
+ szSet: set of Char;
+ // need a delimiter after the token too?, e.g. FOO^BAR^ if FOO^BAR
+ // is the string then only FOO^ is returned, could cause infinite loops
+ // if the condition isn't accounted for thou.
+ bSetTerminator: Boolean;
+ end;
+
+function StrTok(var strr: TStrTokRec): PChar;
+
+type
+
+ PGroupNode = ^TGroupNode;
+
+ TGroupNode = record
+ Left, Right, _prev, _next: PGroupNode;
+ Depth: Cardinal;
+ Hash: Cardinal; // hash of the group name alone
+ szGroup: PChar;
+ cchGroup: Integer;
+ hMenu: THandle;
+ hMenuGroupID: Integer;
+ dwItems: Cardinal;
+ end;
+
+ PGroupNodeList = ^TGroupNodeList;
+
+ TGroupNodeList = record
+ First, Last: PGroupNode;
+ end;
+
+function AllocGroupNode(list: PGroupNodeList; Root: PGroupNode; Depth: Integer): PGroupNode;
+function FindGroupNode(P: PGroupNode; const Hash, Depth: Integer): PGroupNode;
+
+type
+
+ // a contact can never be a submenu too.
+ TSlotDrawType = (dtEntry, dtGroup, dtContact, dtCommand);
+ TSlotDrawTypes = set of TSlotDrawType;
+
+ PMenuDrawInfo = ^TMenuDrawInfo;
+
+ TMenuCommandCallback = function(pipch: PHeaderIPC; // IPC header info, already mapped
+ hWorkThreadEvent: THandle; // event object being waited on on miranda thread
+ hAckEvent: THandle; // ack event object that has been created
+ psd: PMenuDrawInfo // command/draw info
+ ): Integer; stdcall;
+
+ TMenuDrawInfo = record
+ szText: PChar;
+ szProfile: PChar;
+ cch: Integer;
+ wID: Integer; // should be the same as the menu item's ID
+ fTypes: TSlotDrawTypes;
+ hContact: THandle;
+ hStatusIcon: THandle;
+ // HICON from Self^.ProtoIcons[index].hIcons[status]; Do not DestroyIcon()
+ hStatusBitmap: THandle; // HBITMAP, don't free.
+ pid: Integer;
+ MenuCommandCallback: TMenuCommandCallback; // dtCommand must be set also.
+ end;
+
+implementation
+
+{$INCLUDE m_helpers.inc}
+
+function FindGroupNode(P: PGroupNode; const Hash, Depth: Integer): PGroupNode;
+begin
+ Result := P;
+ while Result <> nil do
+ begin
+ if (Result^.Hash = Hash) and (Result^.Depth = Depth) then
+ Exit;
+ If Result^.Left <> nil then
+ begin
+ P := Result;
+ Result := FindGroupNode(Result^.Left, Hash, Depth);
+ If Result <> nil then
+ Exit;
+ Result := P;
+ end;
+ Result := Result^.Right;
+ end; // while
+end;
+
+function AllocGroupNode(list: PGroupNodeList; Root: PGroupNode; Depth: Integer): PGroupNode;
+begin
+ New(Result);
+ Result^.Left := nil;
+ Result^.Right := nil;
+ Result^.Depth := Depth;
+ if Depth > 0 then
+ begin
+ if Root^.Left = nil then
+ Root^.Left := Result
+ else
+ begin
+ Root := Root^.Left;
+ while Root^.Right <> nil do
+ Root := Root^.Right;
+ Root^.Right := Result;
+ end;
+ end
+ else
+ begin
+ if list^.First = nil then
+ list^.First := Result;
+ if list^.Last <> nil then
+ list^.Last^.Right := Result;
+ list^.Last := Result;
+ end; // if
+end;
+
+procedure ipcPrepareRequests(ipcPacketSize: int; pipch: PHeaderIPC; fRequests: Cardinal);
+begin
+ // some fields may already have values like the event object name to open
+ pipch^.cbSize := sizeof(THeaderIPC);
+ pipch^.dwVersion := PLUGIN_MAKE_VERSION(2, 0, 1, 2);
+ pipch^.dwFlags := 0;
+ pipch^.pServerBaseAddress := nil;
+ pipch^.pClientBaseAddress := pipch;
+ pipch^.fRequests := fRequests;
+ pipch^.Slots := 0;
+ pipch^.IconsBegin := nil;
+ pipch^.ContactsBegin := nil;
+ pipch^.GroupsBegin := nil;
+ pipch^.NewIconsBegin := nil;
+ pipch^.DataSize := ipcPacketSize - pipch^.cbSize;
+ // the server side will adjust these pointers as soon as it opens
+ // the mapped file to it's base address, these are set 'ere because ipcAlloc()
+ // maybe used on the client side and are translated by the server side.
+ // ipcAlloc() is used on the client side when transferring filenames
+ // to the ST thread.
+ int_ptr(pipch^.DataPtr) := int_ptr(pipch) + sizeof(THeaderIPC);
+ int_ptr(pipch^.DataPtrEnd) := int_ptr(pipch^.DataPtr) + pipch^.DataSize;
+ pipch^.DataFramePtr := pipch^.DataPtr;
+ // fill the data area
+ FillChar(pipch^.DataPtr^, pipch^.DataSize, 0);
+end;
+
+function ipcSendRequest(hSignal, hWaitFor: THandle; pipch: PHeaderIPC; dwTimeoutMsecs: DWORD)
+ : Cardinal;
+begin
+ { signal ST to work }
+ SetEvent(hSignal);
+ { wait for reply, it should open a handle to hWaitFor... }
+ while True do
+ begin
+ Result := WaitForSingleObjectEx(hWaitFor, dwTimeoutMsecs, True);
+ if Result = WAIT_OBJECT_0 then
+ begin
+ Result := pipch^.fRequests;
+ break;
+ end
+ else if Result = WAIT_IO_COMPLETION then
+ begin
+ (* APC call... *)
+ end
+ else
+ begin
+ Result := REPLY_FAIL;
+ break;
+ end; // if
+ end; // while
+end;
+
+function ipcAlloc(pipch: PHeaderIPC; nSize: Integer): PSlotIPC;
+var
+ PSP: int;
+begin
+ Result := nil;
+ { nSize maybe zero, in that case there is no string section --- }
+ PSP := int(pipch^.DataFramePtr) + sizeof(TSlotIPC) + nSize;
+ { is it past the end? }
+ If PSP >= int(pipch^.DataPtrEnd) then
+ Exit;
+ { return the pointer }
+ Result := pipch^.DataFramePtr;
+ { set up the item }
+ Result^.cbSize := sizeof(TSlotIPC);
+ Result^.cbStrSection := nSize;
+ { update the frame ptr }
+ pipch^.DataFramePtr := Pointer(PSP);
+ { let this item jump to the next yet-to-be-allocated-item which should be null anyway }
+ Result^.Next := Pointer(PSP);
+end;
+
+procedure ipcFixupAddresses(FromServer: LongBool; pipch: PHeaderIPC);
+var
+ pct: PSlotIPC;
+ q: ^PSlotIPC;
+ iServerBase: int_ptr;
+ iClientBase: int_ptr;
+begin
+ if pipch^.pServerBaseAddress = pipch^.pClientBaseAddress then
+ Exit;
+ iServerBase := int_ptr(pipch^.pServerBaseAddress);
+ iClientBase := int_ptr(pipch^.pClientBaseAddress);
+ // fix up all the pointers in the header
+ if pipch^.IconsBegin <> nil then
+ begin
+ int_ptr(pipch^.IconsBegin) := (int_ptr(pipch^.IconsBegin) - iServerBase) + iClientBase;
+ end; // if
+ if pipch^.ContactsBegin <> nil then
+ begin
+ int_ptr(pipch^.ContactsBegin) := (int_ptr(pipch^.ContactsBegin) - iServerBase) +
+ iClientBase;
+ end; // if
+ if pipch^.GroupsBegin <> nil then
+ begin
+ int_ptr(pipch^.GroupsBegin) := (int_ptr(pipch^.GroupsBegin) - iServerBase) + iClientBase;
+ end; // if
+ if pipch^.NewIconsBegin <> nil then
+ begin
+ int_ptr(pipch^.NewIconsBegin) := (int_ptr(pipch^.NewIconsBegin) - iServerBase) +
+ iClientBase;
+ end;
+ int_ptr(pipch^.DataPtr) := (int_ptr(pipch^.DataPtr) - iServerBase) + iClientBase;
+ int_ptr(pipch^.DataPtrEnd) := (int_ptr(pipch^.DataPtrEnd) - iServerBase) + iClientBase;
+ int_ptr(pipch^.DataFramePtr) := (int_ptr(pipch^.DataFramePtr) - iServerBase) + iClientBase;
+ // and the link list
+ pct := pipch^.DataPtr;
+ while (pct <> nil) do
+ begin
+ // the first pointer is already fixed up, have to get a pointer
+ // to the next pointer and modify where it jumps to
+ q := @pct^.Next;
+ if q^ <> nil then
+ begin
+ int_ptr(q^) := (int_ptr(q^) - iServerBase) + iClientBase;
+ end; // if
+ pct := q^;
+ end; // while
+end;
+
+function StrTok(var strr: TStrTokRec): PChar;
+begin
+ Result := nil;
+ { don't allow #0's in sets or null strings }
+ If (strr.szStr = nil) or (#0 in strr.szSet) then
+ Exit;
+ { strip any leading delimiters }
+ while strr.szStr^ in strr.szSet do
+ Inc(strr.szStr);
+ { end on null? full of delimiters }
+ If strr.szStr^ = #0 then
+ begin
+ // wipe out the pointer
+ strr.szStr := nil;
+ Exit;
+ end;
+ { store the start of the token }
+ Result := strr.szStr;
+ { process til start of another delim }
+ while not(strr.szStr^ in strr.szSet) do
+ begin
+ { don't process past the real null, is a delimter required to cap the token? }
+ If strr.szStr^ = #0 then
+ break;
+ Inc(strr.szStr);
+ end;
+ { if we end on a null stop reprocessin' }
+ If strr.szStr^ = #0 then
+ begin
+ // no more tokens can be read
+ strr.szStr := nil;
+ // is a ending delimiter required?
+ If strr.bSetTerminator then
+ begin
+ // rollback
+ strr.szStr := Result;
+ Result := nil;
end;
+ //
+ end
+ else
+ begin
+ { mark the end of the token, may AV if a constant pchar is passed }
+ strr.szStr^ := #0;
+ { skip past this fake null for next time }
+ Inc(strr.szStr);
+ end;
+end;
- - -implementation - - {$include m_helpers.inc} - - function FindGroupNode(P: PGroupNode; const Hash, Depth: Integer): PGroupNode; - begin - Result := P; - while Result <> nil do - begin - if (Result^.Hash = Hash) and (Result^.Depth = Depth) then Exit; - If Result^.Left <> nil then - begin - P := Result; - Result := FindGroupNode(Result^.Left, Hash, Depth); - If Result <> nil then Exit; - Result := P; - end; - Result := Result^.Right; - end; //while - end; - - function AllocGroupNode(list: PGroupNodeList; Root: PGroupNode; Depth: Integer): PGroupNode; - begin - New(Result); - Result^.Left := nil; - Result^.Right := nil; - Result^.Depth := Depth; - if Depth > 0 then - begin - if root^.left = nil then root^.left := Result - else begin - root := root^.left; - while root^.right <> nil do root := root^.right; - root^.right := Result; - end; - end else - begin - if list^.first = nil then list^.first := Result; - if list^.last <> nil then list^.last^.right := Result; - list^.last := Result; - end; //if - end; - - procedure ipcPrepareRequests(ipcPacketSize: int; pipch: PHeaderIPC; fRequests: Cardinal); - begin - // some fields may already have values like the event object name to open - pipch^.cbSize := sizeof(THeaderIPC); - pipch^.dwVersion := PLUGIN_MAKE_VERSION(2,0,1,2); - pipch^.dwFlags := 0; - pipch^.pServerBaseAddress := nil; - pipch^.pClientBaseAddress := pipch; - pipch^.fRequests := fRequests; - pipch^.Slots := 0; - pipch^.IconsBegin := nil; - pipch^.ContactsBegin := nil; - pipch^.GroupsBegin := nil; - pipch^.NewIconsBegin := nil; - pipch^.DataSize := ipcPacketSize - pipch^.cbSize; - // the server side will adjust these pointers as soon as it opens - // the mapped file to it's base address, these are set 'ere because ipcAlloc() - // maybe used on the client side and are translated by the server side. - // ipcAlloc() is used on the client side when transferring filenames - // to the ST thread. - Integer(pipch^.DataPtr) := Integer(pipch) + sizeof(THeaderIPC); - Integer(pipch^.DataPtrEnd) := Integer(pipch^.DataPtr) + pipch^.DataSize; - pipch^.DataFramePtr := pipch^.DataPtr; - // fill the data area - FillChar(pipch^.DataPtr^, pipch^.DataSize, 0); - end; - - function ipcSendRequest(hSignal, hWaitFor: THandle; pipch: PHeaderIPC; dwTimeoutMsecs: DWORD): Cardinal; - begin - { signal ST to work } - SetEvent(hSignal); - { wait for reply, it should open a handle to hWaitFor... } - while True do - begin - Result := WaitForSingleObjectEx(hWaitFor, dwTimeoutMsecs, True); - if Result = WAIT_OBJECT_0 then - begin - Result := pipch^.fRequests; break; - end else if Result = WAIT_IO_COMPLETION then - begin - (* APC call... *) - end else begin - Result := REPLY_FAIL; break; - end; //if - end; //while - end; - - function ipcAlloc(pipch: PHeaderIPC; nSize: Integer): PSlotIPC; - var - PSP: int; - begin - Result := nil; - { nSize maybe zero, in that case there is no string section --- } - PSP := int( pipch^.DataFramePtr ) + sizeof(TSlotIPC) + nSize; - { is it past the end? } - If PSP >= int(pipch^.DataPtrEnd) then Exit; - { return the pointer } - Result := pipch^.DataFramePtr; - { set up the item } - Result^.cbSize := sizeof(TSlotIPC); - Result^.cbStrSection := nSize; - { update the frame ptr } - pipch^.DataFramePtr := Pointer(PSP); - { let this item jump to the next yet-to-be-allocated-item which should be null anyway } - Result^.Next := Pointer(PSP); - end; - - procedure ipcFixupAddresses(FromServer: LongBool; pipch: PHeaderIPC); - var - pct: PSlotIPC; - q: ^PSlotIPC; - iServerBase: Integer; - iClientBase: Integer; - begin - if pipch^.pServerBaseAddress = pipch^.pClientBaseAddress then Exit; - iServerBase := Integer(pipch^.pServerBaseAddress); - iClientBase := Integer(pipch^.pClientBaseAddress); - // fix up all the pointers in the header - if pipch^.iconsBegin <> nil then - begin - Integer(pipch^.IconsBegin) := (Integer(pipch^.IconsBegin) - iServerBase) + iClientBase; - end; //if - if pipch^.contactsBegin <> nil then - begin - Integer(pipch^.ContactsBegin) := (Integer(pipch^.ContactsBegin) - iServerBase) + iClientBase; - end; //if - if pipch^.groupsBegin <> nil then - begin - Integer(pipch^.GroupsBegin) := (Integer(pipch^.GroupsBegin) - iServerBase) + iClientBase; - end; //if - if pipch^.NewIconsBegin <> nil then - begin - Integer(pipch^.NewIconsBegin) := (Integer(pipch^.NewIconsBegin) - iServerBase) + iClientBase; - end; - Integer(pipch^.DataPtr) := (Integer(pipch^.DataPtr) - iServerBase) + iClientBase; - Integer(pipch^.DataPtrEnd) := (Integer(pipch^.DataPtrEnd) - iServerBase) + iClientBase; - Integer(pipch^.DataFramePtr) := (Integer(pipch^.DataFramePtr) - iServerBase) + iClientBase; - // and the link list - pct := pipch^.DataPtr; - while (pct <> nil) do - begin - // the first pointer is already fixed up, have to get a pointer - // to the next pointer and modify where it jumps to - q := @pct^.Next; - if q^ <> nil then - begin - Integer(q^) := (Integer(q^) - iServerBase) + iClientBase; - end; //if - pct := q^; - end; //while - end; - - function StrTok(var strr: TStrTokRec): PChar; - begin - Result := nil; - { don't allow #0's in sets or null strings } - If (strr.szStr = nil) or (#0 in strr.szSet) then Exit; - { strip any leading delimiters } - while strr.szStr^ in strr.szSet do Inc(strr.szStr); - { end on null? full of delimiters } - If strr.szStr^ = #0 then - begin - // wipe out the pointer - strr.szStr := nil; - Exit; - end; - { store the start of the token } - Result := strr.szStr; - { process til start of another delim } - while not (strr.szStr^ in strr.szSet) do - begin - { don't process past the real null, is a delimter required to cap the token? } - If strr.szStr^ = #0 then Break; - Inc(strr.szStr); - end; - { if we end on a null stop reprocessin' } - If strr.szStr^ = #0 then - begin - // no more tokens can be read - strr.szStr := nil; - // is a ending delimiter required? - If strr.bSetTerminator then - begin - // rollback - strr.szStr := Result; - Result := nil; - end; - // - end else - begin - { mark the end of the token, may AV if a constant pchar is passed } - strr.szStr^ := #0; - { skip past this fake null for next time } - Inc(strr.szStr); - end; - end; - end. - - |