/* * Module : Set.cpp * Purpose: NSIS Plug-in for setting shortcut ApplicationID property * Created: 27/12/2009 * Original code Copyright (c) 2009 Mike Anchor. */ /* * Additional Mozilla contributions: * Unicode support * Jump list deletion on uninstall * Pinned item removal on uninstall * contrib: */ #define INITGUID #include #include #include #include #include #pragma comment (lib, "shlwapi.lib") #define MAX_STRLEN 1024 typedef struct _stack_t { struct _stack_t *next; TCHAR text[MAX_PATH]; } stack_t; stack_t **g_stacktop; unsigned int g_stringsize; TCHAR *g_variables; // Indicates that an application supports dual desktop and immersive modes. In Windows 8, this property is only applicable for web browsers. DEFINE_PROPERTYKEY(PKEY_AppUserModel_IsDualMode, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 11); int popstring(TCHAR *str, int len); void pushstring(const TCHAR *str, int len); extern "C" void __declspec(dllexport) Set(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) { g_stringsize = string_size; g_stacktop = stacktop; g_variables = variables; { IPropertyStore *m_pps = NULL; WCHAR wszPath[MAX_PATH]; WCHAR wszAppID[MAX_PATH]; TCHAR szPath[MAX_PATH]; TCHAR szAppID[MAX_PATH]; TCHAR szDualMode[MAX_PATH]; bool success = false; ZeroMemory(wszPath, sizeof(wszPath)); ZeroMemory(wszAppID, sizeof(wszAppID)); ZeroMemory(szPath, sizeof(szPath)); ZeroMemory(szAppID, sizeof(szAppID)); ZeroMemory(szDualMode, sizeof(szDualMode)); popstring(szPath, MAX_PATH); popstring(szAppID, MAX_PATH); bool dualMode = (popstring(szDualMode, MAX_PATH) == 0); // optional #if !defined(UNICODE) MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH); MultiByteToWideChar(CP_ACP, 0, szAppID, -1, wszAppID, MAX_PATH); if (dualMode && stricmp(szDualMode, "true") != 0) { dualMode = false; } #else wcscpy_s(wszPath, szPath); wcscpy_s(wszAppID, szAppID); if (dualMode && _wcsicmp(szDualMode, L"true") != 0) { dualMode = false; } #endif CoInitialize(NULL); if (SUCCEEDED(SHGetPropertyStoreFromParsingName(wszPath, NULL, GPS_READWRITE, IID_PPV_ARGS(&m_pps)))) { PROPVARIANT propvar; if (SUCCEEDED(InitPropVariantFromString(wszAppID, &propvar))) { if (SUCCEEDED(m_pps->SetValue(PKEY_AppUserModel_ID, propvar))) { if (dualMode) { InitPropVariantFromBoolean(true, &propvar); m_pps->SetValue(PKEY_AppUserModel_IsDualMode, propvar); } if (SUCCEEDED(m_pps->Commit())) { success = true; } } } } if (m_pps != NULL) m_pps->Release(); CoUninitialize(); pushstring(success == true ? TEXT("0") : TEXT("-1"), MAX_PATH); } } extern "C" void __declspec(dllexport) UninstallJumpLists(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) { g_stringsize = string_size; g_stacktop = stacktop; g_variables = variables; ICustomDestinationList *m_cdl = NULL; WCHAR wszAppID[MAX_PATH]; TCHAR szAppID[MAX_PATH]; bool success = false; ZeroMemory(wszAppID, sizeof(wszAppID)); ZeroMemory(szAppID, sizeof(szAppID)); popstring(szAppID, MAX_PATH); #if !defined(UNICODE) MultiByteToWideChar(CP_ACP, 0, szAppID, -1, wszAppID, MAX_PATH); #else wcscpy_s(wszAppID, szAppID); #endif CoInitialize(NULL); CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, (void**)&m_cdl); if (m_cdl) { if (SUCCEEDED(m_cdl->DeleteList(wszAppID))) { success = true; } } if (m_cdl) m_cdl->Release(); CoUninitialize(); pushstring(success == true ? TEXT("0") : TEXT("-1"), MAX_PATH); } extern "C" void __declspec(dllexport) UninstallPinnedItem(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) { g_stringsize = string_size; g_stacktop = stacktop; g_variables = variables; IShellItem *pItem = NULL; IStartMenuPinnedList *pPinnedList = NULL; WCHAR wszPath[MAX_PATH]; TCHAR szPath[MAX_PATH]; bool success = false; ZeroMemory(wszPath, sizeof(wszPath)); ZeroMemory(szPath, sizeof(szPath)); popstring(szPath, MAX_PATH); #if !defined(UNICODE) MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH); #else wcscpy_s(wszPath, szPath); #endif CoInitialize(NULL); HRESULT hr; hr = SHCreateItemFromParsingName(wszPath, NULL, IID_PPV_ARGS(&pItem)); if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_StartMenuPin, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pPinnedList)); if (SUCCEEDED(hr)) { hr = pPinnedList->RemoveFromList(pItem); pPinnedList->Release(); success = true; } pItem->Release(); } CoUninitialize(); pushstring(success == true ? TEXT("0") : TEXT("-1"), MAX_PATH); } //Function: Removes the element from the top of the NSIS stack and puts it in the buffer int popstring(TCHAR *str, int len) { stack_t *th; if (!g_stacktop || !*g_stacktop) return 1; th=(*g_stacktop); lstrcpyn(str,th->text, len); *g_stacktop=th->next; GlobalFree((HGLOBAL)th); return 0; } //Function: Adds an element to the top of the NSIS stack void pushstring(const TCHAR *str, int len) { stack_t *th; if (!g_stacktop) return; th=(stack_t*)GlobalAlloc(GPTR, sizeof(stack_t) + len); lstrcpyn(th->text, str, len); th->next=*g_stacktop; *g_stacktop=th; }