summaryrefslogtreecommitdiff
path: root/plugins/ShellExt/src
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2013-08-23 20:47:49 +0000
committerGeorge Hazan <george.hazan@gmail.com>2013-08-23 20:47:49 +0000
commit152e2cbfc1d79cf38a0751ce98bed074cf6c97d4 (patch)
tree6271ece2e5f2614e4613600cfa357ae1ac20caab /plugins/ShellExt/src
parent3cc63733f0d247f133170b2b40fde6ee2e47e870 (diff)
ShellExt: main module completed, one module to go
git-svn-id: http://svn.miranda-ng.org/main/trunk@5797 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/ShellExt/src')
-rw-r--r--plugins/ShellExt/src/shlcom.cpp1280
-rw-r--r--plugins/ShellExt/src/shlcom.h21
-rw-r--r--plugins/ShellExt/src/stdafx.h6
3 files changed, 532 insertions, 775 deletions
diff --git a/plugins/ShellExt/src/shlcom.cpp b/plugins/ShellExt/src/shlcom.cpp
index a77b382f22..8d7103a5a0 100644
--- a/plugins/ShellExt/src/shlcom.cpp
+++ b/plugins/ShellExt/src/shlcom.cpp
@@ -497,7 +497,6 @@ BOOL __stdcall ProcessRequest(HWND hwnd, LPARAM param)
char szBuf[MAX_PATH];
TEnumData *lParam = (TEnumData*)param;
- BOOL Result = true;
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
if (pid != 0) {
@@ -511,7 +510,7 @@ BOOL __stdcall ProcessRequest(HWND hwnd, LPARAM param)
if ( lstrcmpA(szBuf, MIRANDANAME) != 0) {
// opened but not valid.
CloseHandle(hMirandaWorkEvent);
- return Result;
+ return true;
}
}
// if the event object exists, a shlext.dll running in the instance must of created it.
@@ -547,6 +546,7 @@ BOOL __stdcall ProcessRequest(HWND hwnd, LPARAM param)
CloseHandle(hMirandaWorkEvent);
}
}
+ return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -655,6 +655,7 @@ HRESULT TShlComRec::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj
// store the new one && AddRef() it
pDataObject = pdtobj;
pDataObject->AddRef();
+ return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1038,822 +1039,571 @@ HRESULT TClassFactoryRec::LockServer(BOOL)
// IPC part
//
-type
- PFileList = ^TFileList;
- TFileList = array [0 .. 0] of LPSTR;
- PAddArgList = ^TAddArgList;
-
- TAddArgList = record
- szFile: LPSTR; // file being processed
- cch: Cardinal; // it's length (with space for NULL char)
- count: Cardinal; // number we have so far
- files: PFileList;
- hContact: HANDLE;
- hEvent: HANDLE;
- }
-
-function AddToList( args: TAddArgList): LongBool;
-
- attr: Cardinal;
- p: Pointer;
- hFind: HANDLE;
- fd: TWIN32FINDDATA;
- szBuf: array [0 .. MAX_PATH] of Char;
- szThis: LPSTR;
- cchThis: Cardinal;
+struct TAddArgList
{
- Result = false;
- attr = GetFileAttributes(args.szFile);
- if (attr != 0xFFFFFFFF) && ((attr && FILE_ATTRIBUTE_HIDDEN) = 0)
- {
- if args.count mod 10 = 5
- {
- if CallService(MS_SYSTEM_TERMINATED, 0, 0) != 0
- {
- Result = true;
- Exit;
- } // if
- }
- if attr && FILE_ATTRIBUTE_DIRECTORY != 0
- {
- // add the directory
- lstrcpyA(szBuf, args.szFile);
- ReAllocMem(args.files, (args.count + 1) * sizeof(LPSTR));
- 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
- {
- if fd.cFileName[0] != '.'
- {
- 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
- break;
- } // if
- if not FindNextFile(hFind, fd)
- break;
- } // while
- FindClose(hFind);
- }
- else
- {
- // add the file
- ReAllocMem(args.files, (args.count + 1) * sizeof(LPSTR));
- GetMem(p, args.cch);
- lstrcpyA(p, args.szFile);
- args.files^[args.count] = p;
- inc(args.count);
- } // if
- }
-}
+ LPSTR szFile; // file being processed
+ int cch; // it's length (with space for NULL char)
+ int count; // number we have so far
+ LPSTR *files;
+ HANDLE hContact, hEvent;
+};
-procedure MainThreadIssueTransfer(p: PAddArgList); stdcall;
-{$DEFINE SHL_IDC}
-{$DEFINE SHL_KEYS}
-{$INCLUDE shlc.inc}
-{$UNDEF SHL_KEYS}
-{$UNDEF SHL_IDC}
+BOOL AddToList(TAddArgList& args)
{
- DBWriteContactSettingByte(p->hContact, SHLExt_Name, SHLExt_MRU, 1);
- CallService(MS_FILE_SENDSPECIFICFILES, p->hContact, lParam(p->files));
- SetEvent(p->hEvent);
+ char szBuf[MAX_PATH];
+ LPSTR szThis;
+
+ DWORD attr = GetFileAttributesA(args.szFile);
+ if (attr != 0xFFFFFFFF && (attr & FILE_ATTRIBUTE_HIDDEN) == 0) {
+ if ((args.count % 10) == 5)
+ if (CallService(MS_SYSTEM_TERMINATED, 0, 0) != 0)
+ return true;
+
+ if (attr & FILE_ATTRIBUTE_DIRECTORY) {
+ // add the directory
+ lstrcpyA(szBuf, args.szFile);
+ args.files = (LPSTR*)mir_realloc(args.files, (args.count + 1) * sizeof(LPSTR));
+ char *p = mir_strdup(szBuf);
+ args.files[args.count] = p;
+ args.count++;
+ // tack on ending search token
+ lstrcatA(szBuf, "\\*");
+
+ WIN32_FIND_DATAA fd;
+ HANDLE hFind = FindFirstFileA(szBuf, &fd);
+ while (true) {
+ if (fd.cFileName[0] != '.') {
+ 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;
+ int cchThis = args.cch;
+ args.cch = (int)strlen(szBuf) + 1;
+ // recurse
+ BOOL Result = AddToList(args);
+ // restore
+ args.szFile = szThis;
+ args.cch = cchThis;
+ if (Result)
+ return true;
+ }
+ if (!FindNextFileA(hFind, &fd))
+ break;
+ }
+ FindClose(hFind);
+ }
+ else {
+ // add the file
+ args.files = (LPSTR*)mir_realloc(args.files, (args.count + 1) * sizeof(LPSTR));
+ args.files[args.count] = mir_strdup(args.szFile);
+ args.count++;
+ }
+ }
+ return false;
}
-procedure IssueTransferThread(pipch: THeaderIPC *); cdecl;
-
- szBuf: array [0 .. MAX_PATH] of Char;
- pct: TSlotIPC *;
- args: TAddArgList;
- bQuit: LongBool;
- j, c: Cardinal;
- p: Pointer;
- hMainThread: HANDLE;
+void NTAPI MainThreadIssueTransfer(ULONG_PTR param)
{
- hMainThread = HANDLE(pipch->Param);
- GetCurrentDirectory(sizeof(szBuf), szBuf);
- args.count = 0;
- args.files = NULL;
- pct = pipch->DataPtr;
- bQuit = false;
- while pct != NULL do
- {
- if (pct->cbSize != sizeof(TSlotIPC))
- break;
- args.szFile = LPSTR(UINT_PTR(pct) + sizeof(TSlotIPC));
- args.hContact = pct->hContact;
- args.cch = pct->cbStrSection + 1;
- bQuit = AddToList(args);
- if bQuit
- break;
- pct = pct->Next;
- } // while
- if args.files != NULL
- {
- ReAllocMem(args.files, (args.count + 1) * sizeof(LPSTR));
- args.files^[args.count] = NULL;
- inc(args.count);
- if (not bQuit)
- {
- args.hEvent = CreateEvent(NULL, true, false, NULL);
- QueueUserAPC(@MainThreadIssueTransfer, hMainThread, UINT_PTR(@args));
- while true do
- {
- if WaitForSingleObjectEx(args.hEvent, INFINITE, true) != WAIT_IO_COMPLETION
- break;
- }
- CloseHandle(args.hEvent);
- } // if
- c = args.count - 1;
- for j = 0 to c do
- {
- p = args.files^[j];
- if p != NULL
- FreeMem(p);
- }
- FreeMem(args.files);
- }
- SetCurrentDirectory(szBuf);
- FreeMem(pipch);
- CloseHandle(hMainThread);
+ TAddArgList *p = (TAddArgList *)param;
+ db_set_b(p->hContact, SHLExt_Name, SHLExt_MRU, 1);
+ CallService(MS_FILE_SENDSPECIFICFILES, (WPARAM)p->hContact, LPARAM(p->files));
+ SetEvent(p->hEvent);
}
-type
+void __cdecl IssueTransferThread(void *param)
+{
+ THeaderIPC *pipch = (THeaderIPC *)param;
+ HANDLE hMainThread = HANDLE(pipch->Param);
- PSlotInfo = ^TSlotInfo;
+ char szBuf[MAX_PATH];
+ GetCurrentDirectoryA(sizeof(szBuf), szBuf);
- TSlotInfo = record
- hContact: HANDLE;
- hProto: Cardinal;
- dwStatus: Integer; // will be aligned anyway
- }
+ TAddArgList args;
+ args.count = 0;
+ args.files = NULL;
+ TSlotIPC *pct = pipch->DataPtr;
+ BOOL bQuit = false;
+ while (pct != NULL) {
+ if (pct->cbSize != sizeof(TSlotIPC))
+ break;
+ args.szFile = LPSTR(UINT_PTR(pct) + sizeof(TSlotIPC));
+ args.hContact = pct->hContact;
+ args.cch = pct->cbStrSection + 1;
+ bQuit = AddToList(args);
+ if (bQuit)
+ break;
+ pct = pct->Next;
+ } // while
+
+ if (args.files != NULL) {
+ args.files = (LPSTR*)mir_realloc(args.files, (args.count + 1) * sizeof(LPSTR));
+ args.files[args.count] = NULL;
+ args.count++;
+ if (!bQuit) {
+ args.hEvent = CreateEvent(NULL, true, false, NULL);
+ QueueUserAPC(MainThreadIssueTransfer, hMainThread, UINT_PTR(&args));
+ while (true) {
+ if (WaitForSingleObjectEx(args.hEvent, INFINITE, true) != WAIT_IO_COMPLETION)
+ break;
+ }
+ CloseHandle(args.hEvent);
+ }
+ for (int j = 0; j < args.count; j++)
+ mir_free(args.files[j]);
+ mir_free(args.files);
+ }
+ SetCurrentDirectoryA(szBuf);
+ mir_free(pipch);
+ CloseHandle(hMainThread);
+}
- TSlotArray = array [0 .. $FFFFFF] of TSlotInfo;
- PSlotArray = ^TSlotArray;
+struct TSlotInfo
+{
+ HANDLE hContact;
+ int hProto;
+ int dwStatus; // will be aligned anyway
+};
-function SortContact( Item1, Item2: TSlotInfo): Integer; stdcall;
+int __cdecl SortContact(const void *Item1, const void *Item2)
{
- Result = CallService(MS_CLIST_CONTACTSCOMPARE, Item1.hContact, Item2.hContact);
+ return CallService(MS_CLIST_CONTACTSCOMPARE, (WPARAM)((TSlotInfo*)Item1)->hContact, (LPARAM)((TSlotInfo*)Item2)->hContact);
}
-// from FP FCL
-
-procedure QuickSort(FList: PSlotArray; L, R: LongInt);
-
- i, j: LongInt;
- p, q: TSlotInfo;
+void ipcGetSkinIcons(THeaderIPC *ipch)
{
- 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
- {
- q = FList^[i];
- FList^[i] = FList^[j];
- FList^[j] = q;
- inc(i);
- dec(j);
- } // if
- until i > j;
- if L < j
- QuickSort(FList, L, j);
- L = i;
- until i >= R;
+ TSlotProtoIcons spi;
+ char szTmp[64];
+
+ int protoCount;
+ PROTOACCOUNT *pp;
+ if ( CallService(MS_PROTO_ENUMACCOUNTS, WPARAM(&protoCount), LPARAM(&pp)) == 0 && protoCount != 0) {
+ spi.pid = GetCurrentProcessId();
+ while (protoCount > 0) {
+ lstrcpyA(szTmp, pp->szModuleName);
+ lstrcatA(szTmp, PS_GETCAPS);
+ DWORD dwCaps = CallService(szTmp, PFLAGNUM_1, 0);
+ if (dwCaps && PF1_FILESEND) {
+ TSlotIPC *pct = ipcAlloc(ipch, sizeof(TSlotProtoIcons));
+ if (pct != NULL) {
+ // capture all the icons!
+ spi.hProto = mir_hashstr(pp->szModuleName);
+ for (int j = 0; j <= 10; j++)
+ spi.hIcons[j] = LoadSkinnedProtoIcon(pp->szModuleName, ID_STATUS_OFFLINE + j);
+
+ pct->fType = REQUEST_NEWICONS;
+ memcpy(LPSTR(pct) + sizeof(TSlotIPC), &spi, sizeof(TSlotProtoIcons));
+ if (ipch->NewIconsBegin == NULL)
+ ipch->NewIconsBegin = pct;
+ }
+ }
+ pp++;
+ protoCount--;
+ }
+ }
+
+ // add Miranda icon
+ TSlotIPC *pct = ipcAlloc(ipch, sizeof(TSlotProtoIcons));
+ if (pct != NULL) {
+ ZeroMemory(&spi.hIcons, sizeof(spi.hIcons));
+ spi.hProto = 0; // no protocol
+ spi.hIcons[0] = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ pct->fType = REQUEST_NEWICONS;
+ memcpy(LPSTR(pct) + sizeof(TSlotIPC), &spi, sizeof(TSlotProtoIcons));
+ if (ipch->NewIconsBegin == NULL)
+ ipch->NewIconsBegin = pct;
+ }
}
-{$DEFINE SHL_KEYS}
-{$INCLUDE shlc.inc}
-{$UNDEF SHL_KEYS}
+bool ipcGetSortedContacts(THeaderIPC *ipch, int *pSlot, bool bGroupMode)
+{
+ DBVARIANT dbv;
+ int n, rc;
+
+ bool Result = false;
+ // hide offliners?
+ bool bHideOffline = db_get_b(0, "CList", "HideOffline", 0) == 1;
+ // do they wanna hide the offline people anyway?
+ if (db_get_b(0, SHLExt_Name, SHLExt_ShowNoOffline, 0) == 1)
+ // hide offline people
+ bHideOffline = true;
+
+ // get the number of contacts
+ int dwContacts = (int)CallService(MS_DB_CONTACT_GETCOUNT, 0, 0);
+ if (dwContacts == 0)
+ return false;
+
+ // get the contacts in the array to be sorted by status, trim out anyone
+ // who doesn't wanna be seen.
+ TSlotInfo *pContacts = (TSlotInfo*)mir_alloc((dwContacts + 2) * sizeof(TSlotInfo));
+ int i = 0;
+ int dwOnline = 0;
+ for (HANDLE hContact = db_find_first(); hContact != 0; hContact = db_find_next(hContact)) {
+ if (i >= dwContacts)
+ break;
-procedure ipcGetSkinIcons(ipch: THeaderIPC *);
+ // do they have a running protocol?
+ char *szProto = GetContactProto(hContact);
+ if (szProto != NULL) {
+ // does it support file sends?
+ DWORD dwCaps = ProtoCallService(szProto, PS_GETCAPS, PFLAGNUM_1, 0);
+ if ((dwCaps && PF1_FILESEND) == 0)
+ continue;
+
+ int dwStatus = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ if (dwStatus != ID_STATUS_OFFLINE)
+ dwOnline++;
+ else if (bHideOffline)
+ continue;
+
+ // is HIT on?
+ if (BST_UNCHECKED == db_get_b(0, SHLExt_Name, SHLExt_UseHITContacts, BST_UNCHECKED)) {
+ // don't show people who are "Hidden" "NotOnList" | Ignored
+ if (db_get_b(hContact, "CList", "Hidden", 0) == 1 ||
+ db_get_b(hContact, "CList", "NotOnList", 0) == 1 ||
+ CallService(MS_IGNORE_ISIGNORED, (WPARAM)hContact, IGNOREEVENT_MESSAGE | IGNOREEVENT_URL | IGNOREEVENT_FILE) != 0)
+ continue;
+ }
+ // is HIT2 off?
+ if (BST_UNCHECKED == db_get_b(0, SHLExt_Name, SHLExt_UseHIT2Contacts, BST_UNCHECKED))
+ if (db_get_w(hContact, szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ continue;
+
+ // store
+ pContacts[i].hContact = hContact;
+ pContacts[i].dwStatus = dwStatus;
+ pContacts[i].hProto = mir_hashstr(szProto);
+ i++;
+ }
+ }
- protoCount: Integer;
- pp: ^PPROTOCOLDESCRIPTOR;
- spi: TSlotProtoIcons;
- j: Cardinal;
- pct: TSlotIPC *;
- szTmp: array [0 .. 63] of Char;
- dwCaps: Cardinal;
-{
- if (CallService(MS_PROTO_ENUMACCOUNTS, wParam(@protoCount), lParam(@pp)) = 0) &&
- (protoCount != 0)
- {
- spi.pid = GetCurrentProcessId();
- while protoCount > 0 do
- {
- lstrcpyA(szTmp, pp->szName);
- lstrcata(szTmp, PS_GETCAPS);
- dwCaps = CallService(szTmp, PFLAGNUM_1, 0);
- if (dwCaps && PF1_FILESEND) != 0
- {
- pct = ipcAlloc(ipch, sizeof(TSlotProtoIcons));
- if pct != NULL
- {
- // capture all the icons!
- spi.hProto = StrHash(pp->szName);
- for j = 0 to 9 do
- {
- spi.hIcons[j] = LoadSkinnedProtoIcon(pp->szName, ID_STATUS_OFFLINE + j);
- } // for
- pct->fType = REQUEST_NEWICONS;
- CopyMemory(Pointer(UINT_PTR(pct) + sizeof(TSlotIPC)), @spi, sizeof(TSlotProtoIcons));
- if ipch->NewIconsBegin = NULL
- ipch->NewIconsBegin = pct;
- } // if
- } // if
- inc(pp);
- dec(protoCount);
- } // while
- } // if
- // add Miranda icon
- pct = ipcAlloc(ipch, sizeof(TSlotProtoIcons));
- if pct != NULL
- {
- ZeroMemory(@spi.hIcons, sizeof(spi.hIcons));
- spi.hProto = 0; // no protocol
- spi.hIcons[0] = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
- pct->fType = REQUEST_NEWICONS;
- CopyMemory(Pointer(UINT_PTR(pct) + sizeof(TSlotIPC)), @spi, sizeof(TSlotProtoIcons));
- if ipch->NewIconsBegin = NULL
- ipch->NewIconsBegin = pct;
- } // if
-}
+ // if no one is online && the CList isn't showing offliners, quit
+ if (dwOnline == 0 && bHideOffline) {
+ mir_free(pContacts);
+ return false;
+ }
-function ipcGetSortedContacts(ipch: THeaderIPC *; pSlot: pint; bGroupMode: Boolean): Boolean;
-
- dwContacts: Cardinal;
- pContacts: PSlotArray;
- hContact: HANDLE;
- i: Integer;
- dwOnline: Cardinal;
- szProto: LPSTR;
- dwStatus: Integer;
- pct: TSlotIPC *;
- szContact: LPSTR;
- dbv: TDBVariant;
- bHideOffline: Boolean;
- szTmp: array [0 .. 63] of Char;
- dwCaps: Cardinal;
- szSlot: LPSTR;
- n, rc, cch: Cardinal;
-{
- 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
- {
- // hide offline people
- bHideOffline = true;
- }
- // get the number of contacts
- dwContacts = CallService(MS_DB_CONTACT_GETCOUNT, 0, 0);
- if dwContacts = 0
- 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 = db_find_first();
- while (hContact != 0) do
- {
- if i >= dwContacts
- break;
- (* do they have a running protocol? *)
- UINT_PTR(szProto) = CallService(MS_PROTO_GETCONTACTBASEPROTO, hContact, 0);
- if szProto != NULL
- {
- (* does it support file sends? *)
- lstrcpyA(szTmp, szProto);
- lstrcata(szTmp, PS_GETCAPS);
- dwCaps = CallService(szTmp, PFLAGNUM_1, 0);
- if (dwCaps && PF1_FILESEND) = 0
- {
- hContact = db_find_next(hContact);
- continue;
- }
- dwStatus = DBGetContactSettingWord(hContact, szProto, 'Status', ID_STATUS_OFFLINE);
- if dwStatus != ID_STATUS_OFFLINE
- inc(dwOnline)
- else if bHideOffline
- {
- hContact = db_find_next(hContact);
- continue;
- } // if
- // is HIT on?
- if BST_UNCHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseHITContacts,
- BST_UNCHECKED)
- {
- // don't show people who are "Hidden" "NotOnList" | Ignored
- if (DBGetContactSettingByte(hContact, 'CList', 'Hidden', 0) = 1) |
- (DBGetContactSettingByte(hContact, 'CList', 'NotOnList', 0) = 1) |
- (CallService(MS_IGNORE_ISIGNORED, hContact, IGNOREEVENT_MESSAGE |
- IGNOREEVENT_URL | IGNOREEVENT_FILE) != 0)
- {
- hContact = db_find_next(hContact);
- continue;
- } // if
- } // if
- // is HIT2 off?
- if BST_UNCHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_UseHIT2Contacts,
- BST_UNCHECKED)
- {
- if DBGetContactSettingWord(hContact, szProto, 'ApparentMode', 0) = ID_STATUS_OFFLINE
-
- {
- hContact = db_find_next(hContact);
- continue;
- } // if
- } // if
- // store
- pContacts^[i].hContact = hContact;
- pContacts^[i].dwStatus = dwStatus;
- pContacts^[i].hProto = StrHash(szProto);
- inc(i);
- }
- else
- {
- // contact has no protocol!
- } // if
- hContact = db_find_next(hContact);
- } // while
- // if no one is online && the CList isn't showing offliners, quit
- if (dwOnline = 0) && (bHideOffline)
- {
- FreeMem(pContacts);
- Exit;
- } // if
- dwContacts = i;
- i = 0;
- // sort the array
- QuickSort(pContacts, 0, dwContacts - 1);
- // create an IPC slot for each contact && store display name, etc
- while i < dwContacts do
- {
- UINT_PTR(szContact) = CallService(MS_CLIST_GETCONTACTDISPLAYNAME,pContacts^[i].hContact, 0);
- if (szContact != NULL)
- {
- n = 0;
- rc = 1;
- if bGroupMode
- {
- rc = DBGetContactSetting(pContacts^[i].hContact, 'CList', 'Group', @dbv);
- if rc = 0
- {
- n = lstrlenA(dbv.szVal.a) + 1;
- }
- } // if
- cch = lstrlenA(szContact) + 1;
- pct = ipcAlloc(ipch, cch + 1 + n);
- if pct = NULL
- {
- DBFreeVariant(@dbv);
- break;
- }
- // lie about the actual size of the TSlotIPC
- pct->cbStrSection = cch;
- szSlot = LPSTR(UINT_PTR(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 = NULL
- ipch->ContactsBegin = pct;
- inc(szSlot, cch + 1);
- if rc = 0
- {
- pct->hGroup = StrHash(dbv.szVal.a);
- lstrcpyA(szSlot, dbv.szVal.a);
- DBFreeVariant(@dbv);
- }
- else
- {
- pct->hGroup = 0;
- szSlot^ = #0;
- }
- inc(pSlot^);
- } // if
- inc(i);
- } // while
- FreeMem(pContacts);
- //
- Result = true;
+ dwContacts = i;
+ qsort(pContacts, dwContacts, sizeof(TSlotInfo), SortContact);
+
+ // create an IPC slot for each contact && store display name, etc
+ for (i=0; i < dwContacts; i++) {
+ char *szContact = (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)pContacts[i].hContact, 0);
+ if (szContact != NULL) {
+ n = 0;
+ rc = 1;
+ if (bGroupMode) {
+ rc = db_get_s(pContacts[i].hContact, "CList", "Group", &dbv);
+ if (!rc)
+ n = lstrlenA(dbv.pszVal) + 1;
+ }
+ int cch = lstrlenA(szContact) + 1;
+ TSlotIPC *pct = ipcAlloc(ipch, cch + 1 + n);
+ if (pct == NULL) {
+ db_free(&dbv);
+ break;
+ }
+ // lie about the actual size of the TSlotIPC
+ pct->cbStrSection = cch;
+ LPSTR szSlot = LPSTR(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 = db_get_b(pct->hContact, SHLExt_Name, SHLExt_MRU, 0);
+ if (ipch->ContactsBegin == NULL)
+ ipch->ContactsBegin = pct;
+ szSlot += cch + 1;
+ if (rc == 0) {
+ pct->hGroup = mir_hashstr(dbv.pszVal);
+ lstrcpyA(szSlot, dbv.pszVal);
+ db_free(&dbv);
+ }
+ else {
+ pct->hGroup = 0;
+ *szSlot = 0;
+ }
+ pSlot[0]++;
+ }
+ }
+ mir_free(pContacts);
+ return true;
}
// worker thread to clear MRU, called by the IPC bridge
-procedure ClearMRUThread(notused: Pointer); cdecl;
-{$DEFINE SHL_IDC}
-{$DEFINE SHL_KEYS}
-{$INCLUDE shlc.inc}
-{$UNDEF SHL_KEYS}
-{$UNDEF SHL_IDC}
-
- hContact: HANDLE;
+void __cdecl ClearMRUThread(void*)
{
- {
- hContact = db_find_first();
- while hContact != 0 do
- {
- if DBGetContactSettingByte(hContact, SHLExt_Name, SHLExt_MRU, 0) > 0
- {
- DBWriteContactSettingByte(hContact, SHLExt_Name, SHLExt_MRU, 0);
- }
- hContact = db_find_next(hContact);
- }
- }
+ for (HANDLE hContact = db_find_first(); hContact != 0; hContact = db_find_next(hContact))
+ if ( db_get_b(hContact, SHLExt_Name, SHLExt_MRU, 0) > 0)
+ db_set_b(hContact, SHLExt_Name, SHLExt_MRU, 0);
}
// this function is called from an APC into the main thread
-procedure ipcService(dwParam: DWORD); stdcall;
-label
- Reply;
-
- hMap: HANDLE;
- pMMT: THeaderIPC *;
- hSignal: HANDLE;
- pct: TSlotIPC *;
- szBuf: LPSTR;
- iSlot: Integer;
- szGroupStr: array [0 .. 31] of Char;
- dbv: TDBVariant;
- bits: pint;
- bGroupMode: Boolean;
- cloned: THeaderIPC *;
- szMiranda: LPSTR;
+void __stdcall ipcService(ULONG_PTR dwParam)
{
- { 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
- {
- { 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 != NULL) && (pMMT->cbSize = sizeof(THeaderIPC)) &&
- (pMMT->dwVersion = PLUGIN_MAKE_VERSION(2, 0, 1, 2))
- {
- // toggle the right bits
- bits = @pMMT->fRequests;
- // jump right to a worker thread for file processing?
- if (bits^ && REQUEST_XFRFILES) = REQUEST_XFRFILES
- {
- 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);
- mir_forkThread(@IssueTransferThread, cloned);
- goto Reply;
- }
- // the request was to clear the MRU entries, we have no return data
- if (bits^ && REQUEST_CLEARMRU) = REQUEST_CLEARMRU
- {
- mir_forkThread(@ClearMRUThread, NULL);
- goto Reply;
- }
- // 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
- {
- pMMT->dwFlags = HIPC_NOICONS;
- }
- // 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);
-
- // && 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 && (BST_CHECKED = DBGetContactSettingByte(0, SHLExt_Name,
- SHLExt_UseCListSetting, BST_UNCHECKED))
- {
- bGroupMode = 1 = DBGetContactSettingByte(0, 'CList', 'UseGroups', 0);
- }
- iSlot = 0;
- // return profile if set
- if BST_UNCHECKED = DBGetContactSettingByte(0, SHLExt_Name, SHLExt_ShowNoProfile,
- BST_UNCHECKED)
- {
- pct = ipcAlloc(pMMT, 50);
- if pct != NULL
- {
- // 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, UINT_PTR(pct) + sizeof(TSlotIPC));
- } // if
- } // if
- if (bits^ && REQUEST_NEWICONS) = REQUEST_NEWICONS
- {
- ipcGetSkinIcons(pMMT);
- }
- if (bits^ && REQUEST_GROUPS = REQUEST_GROUPS)
- {
- // return contact's grouping if it's present
- while bGroupMode do
- {
- str(iSlot, szGroupStr);
- if DBGetContactSetting(0, 'CListGroups', szGroupStr, @dbv) != 0
- break;
- pct = ipcAlloc(pMMT, lstrlenA(dbv.szVal.a + 1) + 1);
- // first byte has flags, need null term
- if pct != NULL
- {
- if pMMT->GroupsBegin = NULL
- pMMT->GroupsBegin = pct;
- pct->fType = REQUEST_GROUPS;
- pct->hContact = 0;
- UINT_PTR(szBuf) = UINT_PTR(pct) + sizeof(TSlotIPC); // get the } of the slot
- lstrcpyA(szBuf, dbv.szVal.a + 1);
- pct->hGroup = 0;
- DBFreeVariant(@dbv); // free the string
- }
- else
- {
- // outta space
- DBFreeVariant(@dbv);
- break;
- } // if
- inc(iSlot);
- } { while }
- // if there was no space left, it'll } on null
- if pct = NULL
- bits^ = (bits^ | GROUPS_NOTIMPL) && not REQUEST_GROUPS;
- } { if: group request }
- // SHOULD check slot space.
- if (bits^ && REQUEST_CONTACTS = REQUEST_CONTACTS)
- {
- if not ipcGetSortedContacts(pMMT, @iSlot, bGroupMode)
- {
- // fail if there were no contacts AT ALL
- bits^ = (bits^ | CONTACTS_NOTIMPL) && not REQUEST_CONTACTS;
- } // if
- } // 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
- {
- { signal && close }
- SetEvent(hSignal);
- CloseHandle(hSignal);
- }
- { unmap the shared memory from this process }
- UnmapViewOfFile(pMMT);
- }
- { close the map file }
- CloseHandle(hMap);
- } { if }
- //
-}
+ HANDLE hSignal;
+ TSlotIPC *pct;
+ LPSTR szBuf;
+ char szGroupStr[32];
+ DBVARIANT dbv;
+ LPSTR szMiranda;
+
+ // try to open the file mapping object the caller must make sure no other
+ // running instance is using this file
+ HANDLE hMap = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, IPC_PACKET_NAME);
+ if (hMap == 0)
+ return;
-procedure ThreadServer(hMainThread: Pointer); cdecl;
+ // map the file to this process
+ THeaderIPC *pMMT = (THeaderIPC*)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+ // if it fails the caller should of had some timeout in wait
+ if (pMMT != NULL && pMMT->cbSize == sizeof(THeaderIPC) && pMMT->dwVersion == PLUGIN_MAKE_VERSION(2, 0, 1, 2)) {
+ // toggle the right bits
+ int *bits = &pMMT->fRequests;
+ // jump right to a worker thread for file processing?
+ if (*bits & REQUEST_XFRFILES) {
+ THeaderIPC *cloned = (THeaderIPC*)mir_alloc(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);
+ mir_forkthread(&IssueTransferThread, cloned);
+ goto Reply;
+ }
+ // the request was to clear the MRU entries, we have no return data
+ if (*bits & REQUEST_CLEARMRU) {
+ mir_forkthread(&ClearMRUThread, NULL);
+ goto Reply;
+ }
+ // 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 (db_get_b(0, SHLExt_Name, SHLExt_ShowNoIcons, 0) != 0)
+ pMMT->dwFlags = HIPC_NOICONS;
+
+ // see if we have a custom string for 'Miranda'
+ szMiranda = Translate("Miranda");
+ lstrcpynA(pMMT->MirandaName, szMiranda, sizeof(pMMT->MirandaName) - 1);
+
+ // for the MRU menu
+ szBuf = Translate("Recently");
+ lstrcpynA(pMMT->MRUMenuName, szBuf, sizeof(pMMT->MRUMenuName) - 1);
+
+ // && a custom string for "clear entries"
+ szBuf = Translate("Clear entries");
+ lstrcpynA(pMMT->ClearEntries, szBuf, sizeof(pMMT->ClearEntries) - 1);
+
+ // if the group mode is on, check if they want the CList setting
+ bool bGroupMode = (BST_CHECKED == db_get_b(0, SHLExt_Name, SHLExt_UseGroups, BST_UNCHECKED));
+ if (bGroupMode && BST_CHECKED == db_get_b(0, SHLExt_Name, SHLExt_UseCListSetting, BST_UNCHECKED))
+ bGroupMode = (1 == db_get_b(0, "CList", "UseGroups", 0));
+
+ int iSlot = 0;
+ // return profile if set
+ if (BST_UNCHECKED == db_get_b(0, SHLExt_Name, SHLExt_ShowNoProfile, BST_UNCHECKED)) {
+ pct = ipcAlloc(pMMT, 50);
+ if (pct != NULL) {
+ // 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, UINT_PTR(pct) + sizeof(TSlotIPC));
+ }
+ }
+ if (*bits & REQUEST_NEWICONS)
+ ipcGetSkinIcons(pMMT);
+
+ if (*bits & REQUEST_GROUPS) {
+ // return contact's grouping if it's present
+ while (bGroupMode) {
+ _itoa(iSlot, szGroupStr, 10);
+ if ( db_get_s(0, "CListGroups", szGroupStr, &dbv) != 0)
+ break;
+ pct = ipcAlloc(pMMT, lstrlenA(dbv.pszVal + 1) + 1);
+ // first byte has flags, need null term
+ if (pct != NULL) {
+ if (pMMT->GroupsBegin == NULL)
+ pMMT->GroupsBegin = pct;
+ pct->fType = REQUEST_GROUPS;
+ pct->hContact = 0;
+ szBuf = LPSTR(pct) + sizeof(TSlotIPC); // get the end of the slot
+ lstrcpyA(szBuf, dbv.pszVal + 1);
+ pct->hGroup = 0;
+ db_free(&dbv); // free the string
+ }
+ else {
+ // outta space
+ db_free(&dbv);
+ break;
+ }
+ iSlot++;
+ }
+ // if there was no space left, it'll } on null
+ if (pct == NULL)
+ *bits = (*bits | GROUPS_NOTIMPL) & ~REQUEST_GROUPS;
+ }
+ // SHOULD check slot space.
+ if (*bits & REQUEST_CONTACTS) {
+ if (!ipcGetSortedContacts(pMMT, &iSlot, bGroupMode))
+ // fail if there were no contacts AT ALL
+ *bits = (*bits | CONTACTS_NOTIMPL) & ~REQUEST_CONTACTS;
+ }
+ // store the number of slots allocated
+ pMMT->Slots = iSlot;
+Reply:
+ // get the handle the caller wants to be signalled on
+ hSignal = OpenEventA(EVENT_ALL_ACCESS, false, pMMT->SignalEventName);
+ if (hSignal != 0) {
+ SetEvent(hSignal);
+ CloseHandle(hSignal);
+ }
- hEvent: HANDLE;
- retVal: Cardinal;
-{
- hEvent = CreateEvent(NULL, false, false, LPSTR(CreateProcessUID(GetCurrentProcessId())));
- while true do
- {
- retVal = WaitForSingleObjectEx(hEvent, INFINITE, true);
- if retVal = WAIT_OBJECT_0
- {
- QueueUserAPC(@ipcService, HANDLE(hMainThread), 0);
- } // if
- if CallService(MS_SYSTEM_TERMINATED, 0, 0) = 1
- break;
- } // while
- CloseHandle(hEvent);
- CloseHandle(HANDLE(hMainThread));
+ UnmapViewOfFile(pMMT);
+ }
+ CloseHandle(hMap);
}
-procedure InvokeThreadServer;
-
- hMainThread: HANDLE;
+void __cdecl ThreadServer(HANDLE hMainThread)
{
- hMainThread = 0;
- DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), @hMainThread,
- THREAD_SET_CONTEXT, false, 0);
- if hMainThread != 0
- mir_forkThread(@ThreadServer, Pointer(hMainThread));
-}
-
-{ exported functions }
+ HANDLE hEvent = CreateEventA(NULL, false, false, CreateProcessUID(GetCurrentProcessId()).c_str());
+ while (true) {
+ int retVal = WaitForSingleObjectEx(hEvent, INFINITE, true);
+ if (retVal == WAIT_OBJECT_0)
+ QueueUserAPC(ipcService, hMainThread, 0);
-function DllGetClassObject(const CLSID: TCLSID; const IID: TIID; Obj): HResult; stdcall;
-{
- Pointer(Obj) = NULL;
- Result = CLASS_E_CLASSNOTAVAILABLE;
- if (IsEqualCLSID(CLSID, CLSID_ISHLCOM)) && (IsEqualIID(IID, IID_IClassFactory)) &&
- (FindWindow(MirandaName, NULL) != 0)
- {
- Pointer(Obj) = TClassFactoryRec_Create;
- Result = S_OK;
- } // if
+ if (CallService(MS_SYSTEM_TERMINATED, 0, 0) == 1)
+ break;
+ }
+ CloseHandle(hEvent);
+ CloseHandle(hMainThread);
}
-function DllCanUnloadNow: HResult;
+void InvokeThreadServer()
{
- if ((dllpublic.FactoryCount = 0) && (dllpublic.ObjectCount = 0))
- {
- Result = S_OK;
- }
- else
- {
- Result = S_FALSE;
- } // if
+ HANDLE hMainThread = 0;
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThread, THREAD_SET_CONTEXT, false, 0);
+ if (hMainThread != 0)
+ mir_forkthread(&ThreadServer, hMainThread);
}
-{ helper functions }
-
-type
-
- PSHELLEXECUTEINFO = ^TSHELLEXECUTEINFO;
-
- TSHELLEXECUTEINFO = record
- cbSize: DWORD;
- fMask: LongInt;
- hwnd: HANDLE;
- lpVerb: LPSTR;
- lpFile: LPSTR;
- lpParameters: LPSTR;
- lpDirectory: LPSTR;
- nShow: Integer;
- hInstApp: HANDLE;
- lpIDLIst: Pointer;
- lpClass: LPSTR;
- HKEY: HANDLE;
- dwHotkey: DWORD;
- HICON: HANDLE; // is union
- hProcess: HANDLE;
- }
+// exported functions
-function ShellExecuteEx( se: TSHELLEXECUTEINFO): Boolean; stdcall;
- external 'shell32.dll' name 'ShellExecuteExA';
+const IID CLSID_ISHLCOM = { 0x72013A26, 0xA94C, 0x11d6, {0x85, 0x40, 0xA5, 0xE6, 0x29, 0x32, 0x71, 0x1D }};
-function wsprintfs(lpOut, lpFmt: LPSTR; args: LPSTR): Integer; cdecl;
- external 'user32.dll' name 'wsprintfA';
+HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+ if (rclsid == CLSID_ISHLCOM && riid == IID_IClassFactory && FindWindowA(MIRANDANAME, NULL) != 0) {
+ *ppv = new TClassFactoryRec();
+ return S_OK;
+ }
-function RemoveCOMRegistryEntries: HResult;
+ *ppv = NULL;
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
- hRootKey: HKEY;
+HRESULT DllCanUnloadNow()
{
- if RegOpenKeyEx(HKEY_CLASSES_ROOT, 'miranda.shlext', 0, KEY_READ, hRootKey) = ERROR_SUCCESS
-
- {
- (* 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
- {
- MessageBox(0,
- 'Unable to delete registry key for "shlext COM", this key may already be deleted | you may need admin rights.',
- 'Problem', MB_ICONERROR);
- } // if
- } // if
- if RegOpenKeyEx(HKEY_CLASSES_ROOT, '\*\shellex\ContextMenuHandlers', 0, KEY_ALL_ACCESS,
- hRootKey) = ERROR_SUCCESS
- {
- if RegDeleteKey(hRootKey, 'miranda.shlext') != ERROR_SUCCESS
- {
- MessageBox(0,
- 'Unable to delete registry key for "File context menu handlers", this key may already be deleted | you may need admin rights.',
- 'Problem', MB_ICONERROR);
- } // if
- RegCloseKey(hRootKey);
- } // if
- if RegOpenKeyEx(HKEY_CLASSES_ROOT, 'Directory\shellex\ContextMenuHandlers', 0, KEY_ALL_ACCESS,
- hRootKey) = ERROR_SUCCESS
- {
- if RegDeleteKey(hRootKey, 'miranda.shlext') != ERROR_SUCCESS
- {
- MessageBox(0,
- 'Unable to delete registry key for "Directory context menu handlers", this key may already be deleted | you may need admin rights.',
- 'Problem', MB_ICONERROR);
- } // if
- RegCloseKey(hRootKey);
- } // if
- if ERROR_SUCCESS = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- 'Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved', 0, KEY_ALL_ACCESS,
- hRootKey)
- {
- if RegDeleteValue(hRootKey, '{72013A26-A94C-11d6-8540-A5E62932711D}') != ERROR_SUCCESS
- {
- MessageBox(0,
- 'Unable to delete registry entry for "Approved context menu handlers", this key may already be deleted | you may need admin rights.',
- 'Problem', MB_ICONERROR);
- } // if
- RegCloseKey(hRootKey);
- } // if
- Result = S_OK;
+ if (dllpublic.FactoryCount == 0 && dllpublic.ObjectCount == 0)
+ return S_OK;
+ return S_FALSE;
}
-{ called by the options code to remove COM entries, && before that, get permission, if required.
+// helper functions
+
+HRESULT RemoveCOMRegistryEntries()
+{
+ HKEY hRootKey;
+ if ( !RegOpenKeyExA(HKEY_CLASSES_ROOT, "miranda.shlext", 0, KEY_READ, &hRootKey)) {
+ // need to delete the subkey before the parent key is deleted under NT/2000/XP
+ RegDeleteKeyA(hRootKey, "CLSID");
+ // close the key
+ RegCloseKey(hRootKey);
+ // delete it
+ if ( RegDeleteKeyA(HKEY_CLASSES_ROOT, "miranda.shlext") != ERROR_SUCCESS)
+ MessageBoxA(0,
+ "Unable to delete registry key for 'shlext COM', this key may already be deleted or you may need admin rights.",
+ "Problem", MB_ICONERROR);
+ }
+ if ( !RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\*\\shellex\\ContextMenuHandlers", 0, KEY_ALL_ACCESS, &hRootKey)) {
+ if ( RegDeleteKeyA(hRootKey, "miranda.shlext") != ERROR_SUCCESS)
+ MessageBoxA(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);
+ RegCloseKey(hRootKey);
+ }
+ if ( !RegOpenKeyExA(HKEY_CLASSES_ROOT, "Directory\\shellex\\ContextMenuHandlers", 0, KEY_ALL_ACCESS, &hRootKey)) {
+ if ( RegDeleteKeyA(hRootKey, "miranda.shlext") != ERROR_SUCCESS)
+ MessageBoxA(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);
+ RegCloseKey(hRootKey);
+ }
+ if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", 0, KEY_ALL_ACCESS, &hRootKey)) {
+ if ( !RegDeleteValueA(hRootKey, "{72013A26-A94C-11d6-8540-A5E62932711D}") != ERROR_SUCCESS) {
+ MessageBoxA(0,
+ "Unable to delete registry entry for 'Approved context menu handlers', this key may already be deleted | you may need admin rights.",
+ "Problem", MB_ICONERROR);
+ }
+ RegCloseKey(hRootKey);
+ }
+ return S_OK;
}
-procedure CheckUnregisterServer;
+// called by the options code to remove COM entries, && before that, get permission, if required.
- sei: TSHELLEXECUTEINFO;
- szBuf: array [0 .. MAX_PATH * 2] of Char;
- szFileName: array [0 .. MAX_PATH] of Char;
+void CheckUnregisterServer()
{
- if not VistaOrLater
- {
- RemoveCOMRegistryEntries();
- Exit;
- }
- // 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();
+ if (VistaOrLater) {
+ // launches regsvr to remove the dll under admin.
+ char szFileName[MAX_PATH], szBuf[MAX_PATH * 2];
+ GetModuleFileNameA(hInst, szFileName, SIZEOF(szFileName));
+ mir_snprintf(szBuf, sizeof(szBuf), "/s /u \"%s\"", szFileName);
+
+ SHELLEXECUTEINFOA sei = { 0 };
+ sei.cbSize = sizeof(sei);
+ sei.lpVerb = "runas";
+ sei.lpFile = "regsvr32";
+ sei.lpParameters = szBuf;
+ ShellExecuteExA(&sei);
+ Sleep(1000);
+ }
+ RemoveCOMRegistryEntries();
}
-{ Wow, I can't believe there isn't a direct API for this - 'runas' will invoke the UAC && ask
- for permission before installing the shell extension. note the filepath arg has to be quoted }
-procedure CheckRegisterServer;
+// Wow, I can't believe there isn't a direct API for this - 'runas' will invoke the UAC && ask
+// for permission before installing the shell extension. note the filepath arg has to be quoted }
- hRegKey: HKEY;
- sei: TSHELLEXECUTEINFO;
- szBuf: array [0 .. MAX_PATH * 2] of Char;
- szFileName: array [0 .. MAX_PATH] of Char;
+void CheckRegisterServer()
{
- if ERROR_SUCCESS = RegOpenKeyEx(HKEY_CLASSES_ROOT, 'miranda.shlext', 0, KEY_READ, hRegKey)
-
- {
- RegCloseKey(hRegKey);
- }
- else
- {
- if VistaOrLater
- {
- 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 | 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);
- }
- }
+ char szFileName[MAX_PATH], szBuf[MAX_PATH * 2];
+
+ HKEY hRegKey;
+ if ( !RegOpenKeyExA(HKEY_CLASSES_ROOT, "miranda.shlext", 0, KEY_READ, &hRegKey))
+ RegCloseKey(hRegKey);
+ else if (VistaOrLater) {
+ MessageBoxA(0,
+ "Shell context menus requires your permission to register with Windows Explorer (one time only).",
+ "Miranda NG - Shell context menus (shellext.dll)", MB_OK | MB_ICONINFORMATION);
+ // /s = silent
+ GetModuleFileNameA(hInst, szFileName, sizeof(szFileName));
+ mir_snprintf(szBuf, sizeof(szBuf), "/s \"%s\"", szFileName);
+
+ SHELLEXECUTEINFOA sei = { 0 };
+ sei.cbSize = sizeof(sei);
+ sei.lpVerb = "runas";
+ sei.lpFile = "regsvr32";
+ sei.lpParameters = szBuf;
+ ShellExecuteExA(&sei);
+ }
}
diff --git a/plugins/ShellExt/src/shlcom.h b/plugins/ShellExt/src/shlcom.h
index 6aa7377e8c..01461acd8d 100644
--- a/plugins/ShellExt/src/shlcom.h
+++ b/plugins/ShellExt/src/shlcom.h
@@ -94,16 +94,17 @@ struct TSlotIPC
struct THeaderIPC
{
- int cbSize;
- DWORD dwVersion;
- void *pServerBaseAddress, *pClientBaseAddress;
- int fRequests;
- DWORD dwFlags;
- int Slots, Cardinal;
- char SignalEventName[64];
- char MirandaName[64];
- char MRUMenuName[64];
- char ClearEntries[64];
+ int cbSize;
+ DWORD dwVersion;
+ void *pServerBaseAddress, *pClientBaseAddress;
+ int fRequests;
+ DWORD dwFlags;
+ int Slots;
+ HANDLE Param;
+ char SignalEventName[64];
+ char MirandaName[64];
+ char MRUMenuName[64];
+ char ClearEntries[64];
TSlotIPC *IconsBegin, *ContactsBegin, *GroupsBegin, *NewIconsBegin;
// start of an flat memory stack, which is referenced as a linked list
int DataSize;
diff --git a/plugins/ShellExt/src/stdafx.h b/plugins/ShellExt/src/stdafx.h
index 3c231ae4b1..d84021d3e6 100644
--- a/plugins/ShellExt/src/stdafx.h
+++ b/plugins/ShellExt/src/stdafx.h
@@ -5,12 +5,18 @@
#include <ShlObj.h>
#include <Wincodec.h>
+#include <string.h>
#include <string>
#include <newpluginapi.h>
#include <m_system_cpp.h>
#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_file.h>
+#include <m_ignore.h>
+#include <m_skin.h>
+#include <m_clist.h>
#include <m_langpack.h>
#include <m_options.h>
#include <m_database.h>