//#include "stdafx.h"

// Attention: This code DOES NOT work in Win10 Fall Creators Update or later. (2017/10/26)

/*
	Explorer undocumented COM I/F sample by H.Shirouzu
	 Create: 2015/09/16
	 Update: 2015/11/23

	Attention: please use carefully. not abuse
*/

// ForceSetTrayIcon
//	hWnd: NOTIFYICONDATA.hWnd
//	id:   NOTIFYICONDATA.uID
//	pref: 2 is Force Set

BOOL ForceSetTrayIcon(HWND hWnd, UINT id, DWORD pref=2);


struct NOTIFYITEM {
	WCHAR	*exe;
	WCHAR	*tip;
	HICON	hIcon;
	HWND	hWnd;
	DWORD	pref;
	UINT	id;
	GUID	guid;
	void	dummy[8];	// Win10 updated(10586) will access dummy[3] as WCHAR *
};						//  So, it needs to set NULL.

class __declspec(uuid("D782CCBA-AFB0-43F1-94DB-FDA3779EACCB")) INotificationCB : public IUnknown {
public:
	virtual HRESULT __stdcall Notify(u_long, NOTIFYITEM *) = 0;
};

class __declspec(uuid("FB852B2C-6BAD-4605-9551-F15F87830935")) ITrayNotify : public IUnknown {
public:
	virtual HRESULT __stdcall RegisterCallback(INotificationCB *) = 0;
	virtual HRESULT __stdcall SetPreference(const NOTIFYITEM *) = 0;
	virtual HRESULT __stdcall EnableAutoTray(BOOL) = 0;
};
class __declspec(uuid("D133CE13-3537-48BA-93A7-AFCD5D2053B4")) ITrayNotify8 : public IUnknown {
public:
	virtual HRESULT __stdcall RegisterCallback(INotificationCB *, u_long *) = 0;
	virtual HRESULT __stdcall UnregisterCallback(u_long *) = 0;
	virtual HRESULT __stdcall SetPreference(const NOTIFYITEM *) = 0;
	virtual HRESULT __stdcall EnableAutoTray(BOOL) = 0;
	virtual HRESULT __stdcall DoAction(BOOL) = 0;
};
const CLSID TrayNotifyId = {
	0x25DEAD04, 0x1EAC, 0x4911, {0x9E, 0x3A, 0xAD, 0x0A, 0x4A, 0xB5, 0x60, 0xFD}
};

BOOL IsWin8orLater() {
	OSVERSIONINFOEX ovi = { sizeof(ovi), 6, 2 };
	DWORDLONG dwMask = 0;
	VER_SET_CONDITION(dwMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
	VER_SET_CONDITION(dwMask, VER_MINORVERSION, VER_GREATER_EQUAL);
	return VerifyVersionInfo(&ovi, VER_MAJORVERSION | VER_MINORVERSION, dwMask);
}

BOOL ForceSetTrayIcon(HWND hWnd, UINT id, DWORD pref)
{
//	CoInitialize(0);

	BOOL		ret = FALSE;
	NOTIFYITEM	ni = { 0, 0, 0, hWnd, pref, id, 0 };

	if (IsWin8orLater()) {
		ITrayNotify8 *tn = NULL;

		CoCreateInstance(TrayNotifyId, NULL, CLSCTX_LOCAL_SERVER, __uuidof(ITrayNotify8),
			(void **)&tn);
		if (tn) {
			ret = SUCCEEDED(tn->SetPreference(&ni));
			tn->Release();
		}
	} else {
		ITrayNotify *tn = NULL;

		CoCreateInstance(TrayNotifyId, NULL, CLSCTX_LOCAL_SERVER, __uuidof(ITrayNotify),
			(void **)&tn);
		if (tn) {
			ret = SUCCEEDED(tn->SetPreference(&ni));
			tn->Release();
		}
	}
	return	ret;
}