summaryrefslogtreecommitdiff
path: root/plugins/ShellExt
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/ShellExt')
-rw-r--r--plugins/ShellExt/shellext_10.vcxproj1
-rw-r--r--plugins/ShellExt/shellext_10.vcxproj.filters3
-rw-r--r--plugins/ShellExt/shellext_11.vcxproj1
-rw-r--r--plugins/ShellExt/shellext_11.vcxproj.filters3
-rw-r--r--plugins/ShellExt/src/shlcom.cpp75
-rw-r--r--plugins/ShellExt/src/shlicons.cpp71
-rw-r--r--plugins/ShellExt/src/shlicons.h21
7 files changed, 119 insertions, 56 deletions
diff --git a/plugins/ShellExt/shellext_10.vcxproj b/plugins/ShellExt/shellext_10.vcxproj
index fb5ad4ccb5..fb9612b919 100644
--- a/plugins/ShellExt/shellext_10.vcxproj
+++ b/plugins/ShellExt/shellext_10.vcxproj
@@ -201,6 +201,7 @@
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\options.cpp" />
<ClCompile Include="src\shlcom.cpp" />
+ <ClCompile Include="src\shlicons.cpp" />
<ClCompile Include="src\shlipc.cpp" />
<ClCompile Include="src\stdafx.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
diff --git a/plugins/ShellExt/shellext_10.vcxproj.filters b/plugins/ShellExt/shellext_10.vcxproj.filters
index 94085f5086..edd3cd00af 100644
--- a/plugins/ShellExt/shellext_10.vcxproj.filters
+++ b/plugins/ShellExt/shellext_10.vcxproj.filters
@@ -55,5 +55,8 @@
<ClCompile Include="src\shlipc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\shlicons.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/plugins/ShellExt/shellext_11.vcxproj b/plugins/ShellExt/shellext_11.vcxproj
index 8b133f32fc..a69693f4a5 100644
--- a/plugins/ShellExt/shellext_11.vcxproj
+++ b/plugins/ShellExt/shellext_11.vcxproj
@@ -204,6 +204,7 @@
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\options.cpp" />
<ClCompile Include="src\shlcom.cpp" />
+ <ClCompile Include="src\shlicons.cpp" />
<ClCompile Include="src\shlipc.cpp" />
<ClCompile Include="src\stdafx.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
diff --git a/plugins/ShellExt/shellext_11.vcxproj.filters b/plugins/ShellExt/shellext_11.vcxproj.filters
index 94085f5086..edd3cd00af 100644
--- a/plugins/ShellExt/shellext_11.vcxproj.filters
+++ b/plugins/ShellExt/shellext_11.vcxproj.filters
@@ -55,5 +55,8 @@
<ClCompile Include="src\shlipc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\shlicons.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/plugins/ShellExt/src/shlcom.cpp b/plugins/ShellExt/src/shlcom.cpp
index 11c6616116..d4efcd09c6 100644
--- a/plugins/ShellExt/src/shlcom.cpp
+++ b/plugins/ShellExt/src/shlcom.cpp
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "shlcom.h"
+#include "shlicons.h"
static bool VistaOrLater;
@@ -59,14 +60,14 @@ int IsCOMRegistered()
static string CreateProcessUID(int pid)
{
char buf[100];
- mir_snprintf(buf, sizeof(buf), "mim.shlext.%d$", pid);
+ sprintf_s(buf, sizeof(buf), "mim.shlext.%d$", pid);
return buf;
}
static string CreateUID()
{
char buf[100];
- mir_snprintf(buf, sizeof(buf), "'mim.shlext.caller%d$%d", GetCurrentProcessId(), GetCurrentThreadId());
+ sprintf_s(buf, sizeof(buf), "'mim.shlext.caller%d$%d", GetCurrentProcessId(), GetCurrentThreadId());
return buf;
}
@@ -467,33 +468,40 @@ void BuildMenus(TEnumData *lParam)
void BuildSkinIcons(TEnumData *lParam)
{
- TSlotIPC *pct;
- TShlComRec *Self;
- UINT j;
+ IWICImagingFactory *factory = (VistaOrLater) ? ARGB_GetWorker() : NULL;
- pct = lParam->ipch->NewIconsBegin;
- Self = lParam->Self;
+ TSlotIPC *pct = lParam->ipch->NewIconsBegin;
+ TShlComRec *Self = lParam->Self;
while (pct != NULL) {
if (pct->cbSize != sizeof(TSlotIPC) || pct->fType != REQUEST_NEWICONS)
break;
TSlotProtoIcons *p = (TSlotProtoIcons*)(PBYTE(pct) + sizeof(TSlotIPC));
- Self->ProtoIcons = (TSlotProtoIcons*)mir_realloc(Self->ProtoIcons, (Self->ProtoIconsCount + 1) * sizeof(TSlotProtoIcons));
+ Self->ProtoIcons = (TSlotProtoIcons*)realloc(Self->ProtoIcons, (Self->ProtoIconsCount + 1) * sizeof(TSlotProtoIcons));
TSlotProtoIcons *d = &Self->ProtoIcons[Self->ProtoIconsCount];
memmove(d, p, sizeof(TSlotProtoIcons));
- // if using Vista (| later), clone all the icons into bitmaps && keep these around,
- // if using anything older, just use the default code, the bitmaps (&& | icons) will be freed
+ // if using Vista (or later), clone all the icons into bitmaps and keep these around,
+ // if using anything older, just use the default code, the bitmaps (and/or icons) will be freed
// with the shell object.
- for (j = 0; j < 10; j++) {
- d->hBitmaps[j] = 0;
- d->hIcons[j] = CopyIcon(p->hIcons[j]);
+ for (int j = 0; j < 10; j++) {
+ if (VistaOrLater) {
+ d->hBitmaps[j] = ARGB_BitmapFromIcon(factory, Self->hMemDC, p->hIcons[j]);
+ d->hIcons[j] = NULL;
+ }
+ else {
+ d->hBitmaps[j] = NULL;
+ d->hIcons[j] = CopyIcon(p->hIcons[j]);
+ }
}
Self->ProtoIconsCount++;
pct = pct->Next;
}
+
+ if (factory)
+ factory->Release();
}
BOOL __stdcall ProcessRequest(HWND hwnd, LPARAM param)
@@ -513,7 +521,7 @@ BOOL __stdcall ProcessRequest(HWND hwnd, LPARAM param)
hMirandaWorkEvent = OpenEventA(EVENT_ALL_ACCESS, false, CreateProcessUID(pid).c_str());
if (hMirandaWorkEvent != 0) {
GetClassNameA(hwnd, szBuf, sizeof(szBuf));
- if ( lstrcmpA(szBuf, MIRANDANAME) != 0) {
+ if ( lstrcmpA(szBuf, MIRANDACLASS) != 0) {
// opened but not valid.
CloseHandle(hMirandaWorkEvent);
return true;
@@ -559,8 +567,6 @@ BOOL __stdcall ProcessRequest(HWND hwnd, LPARAM param)
TShlComRec::TShlComRec()
{
- HDC DC;
-
RefCount = 1;
hDllHeap = HeapCreate(0, 0, 0);
hRootMenu = 0;
@@ -571,7 +577,7 @@ TShlComRec::TShlComRec()
ProtoIcons = NULL;
ProtoIconsCount = 0;
// create an inmemory DC
- DC = GetDC(0);
+ HDC DC = GetDC(0);
hMemDC = CreateCompatibleDC(DC);
ReleaseDC(0, DC);
// keep count on the number of objects
@@ -624,7 +630,7 @@ ULONG TShlComRec::Release()
DeleteObject(p->hBitmaps[j]);
}
}
- mir_free(ProtoIcons);
+ free(ProtoIcons);
ProtoIcons = NULL;
}
// free IDataObject reference if pointer exists
@@ -679,17 +685,13 @@ HRESULT TShlComRec::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT _idCmdFir
if (((LOWORD(uFlags) & CMF_VERBSONLY) != CMF_VERBSONLY) && ((LOWORD(uFlags) & CMF_DEFAULTONLY) != CMF_DEFAULTONLY)) {
bool bMF_OWNERDRAW = false;
// get the shell version
- HINSTANCE hShellInst = LoadLibraryA("shell32.dll");
- if (hShellInst != 0) {
- pfnDllGetVersion DllGetVersionProc = (pfnDllGetVersion)GetProcAddress(hShellInst, "DllGetVersion");
- if (DllGetVersionProc != NULL) {
- DllVersionInfo dvi;
- dvi.cbSize = sizeof(dvi);
- if (DllGetVersionProc(&dvi) >= 0)
- // it's at least 4.00
- bMF_OWNERDRAW = (dvi.dwMajorVersion > 4) | (dvi.dwMinorVersion >= 71);
- }
- FreeLibrary(hShellInst);
+ pfnDllGetVersion DllGetVersionProc = (pfnDllGetVersion)GetProcAddress( GetModuleHandleA("shell32.dll"), "DllGetVersion");
+ if (DllGetVersionProc != NULL) {
+ DllVersionInfo dvi;
+ dvi.cbSize = sizeof(dvi);
+ if (DllGetVersionProc(&dvi) >= 0)
+ // it's at least 4.00
+ bMF_OWNERDRAW = (dvi.dwMajorVersion > 4) | (dvi.dwMinorVersion >= 71);
}
// if we're using Vista (| later), the ownerdraw code will be disabled, because the system draws the icons.
@@ -719,7 +721,7 @@ HRESULT TShlComRec::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT _idCmdFir
// create the wait wait-for-wait object
ed.hWaitFor = CreateEventA(NULL, false, false, pipch->SignalEventName);
if (ed.hWaitFor != 0) {
- // enumerate all the top level windows to find all loaded MIRANDANAME classes
+ // enumerate all the top level windows to find all loaded MIRANDACLASS classes
EnumWindows(&ProcessRequest, LPARAM(&ed));
// close the wait-for-reply object
CloseHandle(ed.hWaitFor);
@@ -1184,20 +1186,21 @@ void ipcGetSkinIcons(THeaderIPC *ipch)
char szTmp[64];
int protoCount;
- PROTOACCOUNT *pp;
+ PROTOACCOUNT **pp;
if ( CallService(MS_PROTO_ENUMACCOUNTS, WPARAM(&protoCount), LPARAM(&pp)) == 0 && protoCount != 0) {
spi.pid = GetCurrentProcessId();
while (protoCount > 0) {
- lstrcpyA(szTmp, pp->szModuleName);
+ PROTOACCOUNT *pa = *pp;
+ lstrcpyA(szTmp, pa->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);
+ spi.hProto = mir_hashstr(pa->szModuleName);
for (int j = 0; j <= 10; j++)
- spi.hIcons[j] = LoadSkinnedProtoIcon(pp->szModuleName, ID_STATUS_OFFLINE + j);
+ spi.hIcons[j] = LoadSkinnedProtoIcon(pa->szModuleName, ID_STATUS_OFFLINE + j);
pct->fType = REQUEST_NEWICONS;
memcpy(LPSTR(pct) + sizeof(TSlotIPC), &spi, sizeof(TSlotProtoIcons));
@@ -1510,9 +1513,7 @@ const IID CLSID_ISHLCOM = { 0x72013A26, 0xA94C, 0x11d6, {0x85, 0x40, 0xA5, 0xE6,
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
- MessageBoxA(0, "Ding!", "Dong", MB_OK);
-
- if (rclsid == CLSID_ISHLCOM && riid == IID_IClassFactory && FindWindowA(MIRANDANAME, NULL) != 0) {
+ if (rclsid == CLSID_ISHLCOM && riid == IID_IClassFactory && FindWindowA(MIRANDACLASS, NULL) != 0) {
*ppv = new TClassFactoryRec();
return S_OK;
}
diff --git a/plugins/ShellExt/src/shlicons.cpp b/plugins/ShellExt/src/shlicons.cpp
new file mode 100644
index 0000000000..20f941a03e
--- /dev/null
+++ b/plugins/ShellExt/src/shlicons.cpp
@@ -0,0 +1,71 @@
+#include "stdafx.h"
+#include "shlicons.h"
+
+#pragma comment(lib, "windowscodecs.lib")
+/*
+The following implementation has been ported from:
+
+http://web.archive.org/web/20080121112802/http://shellrevealed.com/blogs/shellblog/archive/2007/02/06/Vista-Style-Menus_2C00_-Part-1-_2D00_-Adding-icons-to-standard-menus.aspx
+
+It uses WIC (Windows Imaging Codec) to convert the given Icon into a bitmap in ARGB format, this is required
+by Windows for use as an icon (but in bitmap format), so that Windows draws everything (including theme)
+so we don't have to.
+
+Why didn't they just do this themselves? ...
+*/
+
+/*
+ The object returned from this function has to be released using the QI COM interface, don't forget.
+ Note this function won't work on anything where WIC isn't installed (XP can have it installed, but not by default)
+ anything less won't work.
+*/
+
+IWICImagingFactory* ARGB_GetWorker()
+{
+ IWICImagingFactory *res = NULL;
+ CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (void**)&res);
+ return res;
+}
+
+HBITMAP ARGB_BitmapFromIcon(IWICImagingFactory *Factory, HDC hDC, HICON hIcon)
+{
+ HBITMAP hBmp = NULL;
+
+ // This code gives an icon to WIC and gets a bitmap object in return, it then creates a DIB section
+ // which is 32bits and the same H*W as the icon. It then asks the bitmap object to copy itself into the DIB }
+
+ BITMAPINFO bmi = { 0 };
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biBitCount = 32;
+
+ IWICBitmap *bitmap = NULL;
+ HRESULT hr = Factory->CreateBitmapFromHICON(hIcon, &bitmap);
+ if (hr == S_OK) {
+ int cx, cy;
+ hr = bitmap->GetSize((PUINT)&cx, (PUINT)&cy);
+ if (hr == S_OK) {
+ bmi.bmiHeader.biWidth = cx;
+ bmi.bmiHeader.biHeight = -cy;
+
+ void *pbBuffer;
+ hBmp = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &pbBuffer, 0, 0);
+ if (hBmp != 0) {
+ UINT cbStride = cx * sizeof(DWORD); // ARGB = DWORD
+ UINT cbBuffer = cy * cbStride;
+ // note: the pbBuffer memory is owned by the DIB and will be freed when the bitmap is released
+ hr = bitmap->CopyPixels(NULL, cbStride, cbBuffer, (PBYTE)pbBuffer);
+ if (hr != S_OK) {
+ // the copy failed, delete the DIB
+ DeleteObject(hBmp);
+ hBmp = NULL;
+ }
+ }
+ }
+ // release the bitmap object now
+ bitmap->Release();
+ }
+
+ return hBmp;
+}
diff --git a/plugins/ShellExt/src/shlicons.h b/plugins/ShellExt/src/shlicons.h
index 8405bf69cc..6010c8c489 100644
--- a/plugins/ShellExt/src/shlicons.h
+++ b/plugins/ShellExt/src/shlicons.h
@@ -1,21 +1,4 @@
-struct TWICBitmap : public IWICBitmapSource
-{
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
- virtual ULONG STDMETHODCALLTYPE AddRef(void);
- virtual ULONG STDMETHODCALLTYPE Release(void);
+IWICImagingFactory* ARGB_GetWorker();
- virtual HRESULT STDMETHODCALLTYPE GetSize(UINT *puiWidth, UINT *puiHeight);
- virtual HRESULT STDMETHODCALLTYPE GetPixelFormat(WICPixelFormatGUID *pPixelFormat);
- virtual HRESULT STDMETHODCALLTYPE GetResolution(double *pDpiX, double *pDpiY);
- virtual HRESULT STDMETHODCALLTYPE CopyPalette(IWICPalette *pIPalette);
- virtual HRESULT STDMETHODCALLTYPE CopyPixels(const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer);
-};
-
-struct TImageFactory : public IImagingFactory
-{
-};
-
-TImageFactory* ARGB_GetWorker();
-
-HBITMAP ARGB_BitmapFromIcon(TImageFactory* Factory, HDC hdc, HICON hIcon);
+HBITMAP ARGB_BitmapFromIcon(IWICImagingFactory *Factory, HDC hdc, HICON hIcon);