summaryrefslogtreecommitdiff
path: root/plugins/ShlExt
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/ShlExt')
-rw-r--r--plugins/ShlExt/inc/README.txt92
-rw-r--r--plugins/ShlExt/inc/m_addcontact.inc54
-rw-r--r--plugins/ShlExt/inc/m_api.pas75
-rw-r--r--plugins/ShlExt/inc/m_awaymsg.inc40
-rw-r--r--plugins/ShlExt/inc/m_clc.inc284
-rw-r--r--plugins/ShlExt/inc/m_clist.inc641
-rw-r--r--plugins/ShlExt/inc/m_clui.inc215
-rw-r--r--plugins/ShlExt/inc/m_contacts.inc90
-rw-r--r--plugins/ShlExt/inc/m_database.inc654
-rw-r--r--plugins/ShlExt/inc/m_email.inc39
-rw-r--r--plugins/ShlExt/inc/m_file.inc66
-rw-r--r--plugins/ShlExt/inc/m_findadd.inc38
-rw-r--r--plugins/ShlExt/inc/m_globaldefs.pas99
-rw-r--r--plugins/ShlExt/inc/m_globaldefs.ppubin8913 -> 0 bytes
-rw-r--r--plugins/ShlExt/inc/m_helpers.inc613
-rw-r--r--plugins/ShlExt/inc/m_history.inc37
-rw-r--r--plugins/ShlExt/inc/m_icq.inc191
-rw-r--r--plugins/ShlExt/inc/m_ignore.inc74
-rw-r--r--plugins/ShlExt/inc/m_langpack.inc82
-rw-r--r--plugins/ShlExt/inc/m_message.inc57
-rw-r--r--plugins/ShlExt/inc/m_netlib.inc713
-rw-r--r--plugins/ShlExt/inc/m_options.inc109
-rw-r--r--plugins/ShlExt/inc/m_plugins.inc70
-rw-r--r--plugins/ShlExt/inc/m_popup.inc222
-rw-r--r--plugins/ShlExt/inc/m_protocols.inc180
-rw-r--r--plugins/ShlExt/inc/m_protomod.inc105
-rw-r--r--plugins/ShlExt/inc/m_protosvc.inc753
-rw-r--r--plugins/ShlExt/inc/m_skin.inc120
-rw-r--r--plugins/ShlExt/inc/m_system.inc170
-rw-r--r--plugins/ShlExt/inc/m_url.inc39
-rw-r--r--plugins/ShlExt/inc/m_userinfo.inc84
-rw-r--r--plugins/ShlExt/inc/m_utils.inc279
-rw-r--r--plugins/ShlExt/inc/m_v8.inc62
-rw-r--r--plugins/ShlExt/inc/newpluginapi.inc94
-rw-r--r--plugins/ShlExt/inc/statusmodes.inc54
-rw-r--r--plugins/ShlExt/inc/testdll.dpr60
-rw-r--r--plugins/ShlExt/shlc.inc315
-rw-r--r--plugins/ShlExt/shlcom.pas4879
-rw-r--r--plugins/ShlExt/shlext.dpr782
-rw-r--r--plugins/ShlExt/shlicons.pas330
-rw-r--r--plugins/ShlExt/shlipc.pas757
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
deleted file mode 100644
index dff0527ff7..0000000000
--- a/plugins/ShlExt/inc/m_globaldefs.ppu
+++ /dev/null
Binary files differ
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.
-
-