From 152e2cbfc1d79cf38a0751ce98bed074cf6c97d4 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 23 Aug 2013 20:47:49 +0000 Subject: ShellExt: main module completed, one module to go git-svn-id: http://svn.miranda-ng.org/main/trunk@5797 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/ShellExt/src/shlcom.cpp | 1280 ++++++++++++++++----------------------- plugins/ShellExt/src/shlcom.h | 21 +- plugins/ShellExt/src/stdafx.h | 6 + 3 files changed, 532 insertions(+), 775 deletions(-) (limited to 'plugins') 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 #include +#include #include #include #include #include +#include +#include +#include +#include +#include #include #include #include -- cgit v1.2.3