From 3383932a9bdee5d1166e8fdb560079da517fb568 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Sat, 24 Aug 2013 09:14:28 +0000 Subject: - ShellExt: Delphi plugin moved to Deprecated C++ plugin added to solutions Preferences moved from 'Plugins' to 'Services' git-svn-id: http://svn.miranda-ng.org/main/trunk@5807 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/!Deprecated/ShlExt/shlext.dpr | 379 ++++++++++++++++++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100644 plugins/!Deprecated/ShlExt/shlext.dpr (limited to 'plugins/!Deprecated/ShlExt/shlext.dpr') diff --git a/plugins/!Deprecated/ShlExt/shlext.dpr b/plugins/!Deprecated/ShlExt/shlext.dpr new file mode 100644 index 0000000000..c23ee75f93 --- /dev/null +++ b/plugins/!Deprecated/ShlExt/shlext.dpr @@ -0,0 +1,379 @@ +{$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_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 + 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}="" + 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; +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 = MessageBoxW(0, + TranslateW( + 'Are you sure? this will remove all the settings stored in your database and all registry entries created for shlext to work with Explorer'), + TranslateW('Disable/Remove shlext'), MB_YESNO or MB_ICONQUESTION) then + begin + db_unset(0, SHLExt_Name, SHLExt_UseGroups); + db_unset(0, SHLExt_Name, SHLExt_UseCListSetting); + db_unset(0, SHLExt_Name, SHLExt_UseHITContacts); + db_unset(0, SHLExt_Name, SHLExt_UseHIT2Contacts); + db_unset(0, SHLExt_Name, SHLExt_ShowNoProfile); + db_unset(0, SHLExt_Name, SHLExt_ShowNoIcons); + db_unset(0, SHLExt_Name, SHLExt_ShowNoOffline); + + (* 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; + + Options_AddPage(wParam,@optDialog); +end; + +function MirandaPluginInfoEx(mirandaVersion: DWORD): PPLUGININFOEX; cdecl; +begin + Result := nil; + { fill in plugininfo } + PluginInfo.cbSize := sizeof(PluginInfo); + PluginInfo.shortName := 'Shell context menus for transfers'; + PluginInfo.version := PLUGIN_MAKE_VERSION(2, 0, 1, 2); +{$IFDEF FPC} + PluginInfo.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.'; +{$ELSE} + PluginInfo.description := ''; +{$ENDIF} + PluginInfo.author := 'egoDust'; + PluginInfo.authorEmail := 'egodust@users.sourceforge.net'; + PluginInfo.copyright := '(c) 2009 Sam Kothari (egoDust)'; + PluginInfo.homePage := 'http://addons.miranda-im.org/details.php?action=viewfile&id=534'; + PluginInfo.flags := 0; + { This UUID is fetched twice } + CopyMemory(@PluginInfo.uuid, @CLSID_ISHLCOM, sizeof(TMUUID)); + { return info } + Result := @PluginInfo; +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; + +initialization + DisableThreadLibraryCalls(hInstance); + +end. -- cgit v1.2.3