OSDN Git Service

Merge pull request #101 from GreyMerlin/master
[winmerge-jp/winmerge-jp.git] / Src / JumpList.cpp
1 /** 
2  * @file  JumpList.cpp
3  *
4  * @brief Implementation file for JumpList helper functions.
5  *
6  */
7 #include "JumpList.h"
8 #include <vector>
9 #pragma warning (push)                  // prevent "warning C4091: 'typedef ': ignored on left of 'tagGPFIDL_FLAGS' when no variable is declared"
10 #pragma warning (disable:4091)  // VC bug when using XP enabled toolsets.
11 #include <shlobj.h>
12 #pragma warning (pop)
13 #include <propvarutil.h>
14 #include <propkey.h>
15 #include "unicoder.h"
16
17 namespace
18 {
19
20 std::wstring g_appid;
21 wchar_t g_exe_path[260];
22
23 IShellLinkW *CreateShellLink(const std::wstring& app_path, const std::wstring& params, const std::wstring& title, const std::wstring& desc, int icon_index)
24 {
25         IShellLinkW *pShellLink = nullptr;
26         if (FAILED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER,
27                                     IID_IShellLinkW, (void **)&pShellLink)))
28                 return nullptr;
29
30         std::wstring app_path2(app_path);
31         if (app_path.empty())
32         {
33                 if (g_exe_path[0] == '\0')
34                         GetModuleFileNameW(nullptr, g_exe_path, sizeof(g_exe_path)/sizeof(g_exe_path[0]));
35                 app_path2 = g_exe_path;
36         }
37         pShellLink->SetPath(app_path2.c_str());
38         pShellLink->SetIconLocation(app_path2.c_str(), icon_index);
39         pShellLink->SetArguments(params.c_str());
40         pShellLink->SetDescription(desc.c_str());
41
42         IPropertyStore *pPS = nullptr;
43         if (SUCCEEDED(pShellLink->QueryInterface(IID_IPropertyStore, (void **)&pPS)))
44         {
45                 PROPVARIANT pv;
46                 if (SUCCEEDED(InitPropVariantFromString(title.c_str(), &pv)))
47                 {
48                         pPS->SetValue(PKEY_Title, pv);
49                         PropVariantClear(&pv);
50                 }
51                 pPS->Commit();
52                 pPS->Release();
53         }
54
55         return pShellLink;
56 }
57
58 }
59
60 namespace JumpList
61 {
62
63 bool SetCurrentProcessExplicitAppUserModelID(const std::wstring& appid)
64 {
65         g_appid = appid;
66         HMODULE hLibrary = GetModuleHandle(_T("shell32.dll"));
67         if (hLibrary == nullptr)
68                 return false;
69         HRESULT (__stdcall *pfnSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID) = 
70                 (HRESULT (__stdcall *)(PCWSTR))GetProcAddress(hLibrary, "SetCurrentProcessExplicitAppUserModelID");
71         if (pfnSetCurrentProcessExplicitAppUserModelID == nullptr)
72                 return false;
73         return pfnSetCurrentProcessExplicitAppUserModelID(appid.c_str()) == S_OK;
74 }
75
76 bool AddToRecentDocs(const String& app_path, const String& params, const String& title, const String& desc, int icon_index)
77 {
78         SHARDAPPIDINFOLINK saiil;
79         saiil.pszAppID = g_appid.c_str();
80 #ifdef _UNICODE
81         saiil.psl = CreateShellLink(app_path, params, title, desc, icon_index);
82 #else
83         saiil.psl = (IShellLink *)CreateShellLink(ucr::toUTF16(app_path), ucr::toUTF16(params), ucr::toUTF16(title), ucr::toUTF16(desc), icon_index);
84 #endif
85         if (saiil.psl == nullptr)
86                 return false;
87         SHAddToRecentDocs(SHARD_APPIDINFOLINK, &saiil);
88         saiil.psl->Release();
89         return true;
90 }
91
92 std::vector<Item> GetRecentDocs(size_t nMaxItems)
93 {
94         std::vector<Item> list;
95         IApplicationDocumentLists *pDocumentLists = nullptr;
96         if (FAILED(CoCreateInstance(CLSID_ApplicationDocumentLists, nullptr, CLSCTX_INPROC_SERVER,
97                                     IID_IApplicationDocumentLists, (void **)&pDocumentLists)))
98                 return list;
99         pDocumentLists->SetAppID(g_appid.c_str());
100
101         IObjectArray *pObjectArray;
102         if (SUCCEEDED(pDocumentLists->GetList(ADLT_RECENT, static_cast<UINT>(nMaxItems), IID_IObjectArray, (void **)&pObjectArray)))
103         {
104                 UINT nObjects;
105                 if (SUCCEEDED(pObjectArray->GetCount(&nObjects)))
106                 {
107                         for (UINT i = 0; i < nObjects; ++i)
108                         {
109                                 IShellLinkW *pShellLink;
110                                 if (SUCCEEDED(pObjectArray->GetAt(i, IID_IShellLinkW, (void **)&pShellLink)))
111                                 {
112                                         wchar_t szPath[MAX_PATH];
113                                         wchar_t szDescription[MAX_PATH];
114                                         wchar_t szArguments[MAX_PATH * 6];
115                                         pShellLink->GetPath(szPath, sizeof(szPath) / sizeof(szPath[0]), nullptr, SLGP_RAWPATH);
116                                         pShellLink->GetDescription(szDescription, sizeof(szDescription) / sizeof(szDescription[0]));
117                                         pShellLink->GetArguments(szArguments, sizeof(szArguments) / sizeof(szArguments[0]));
118                                         IPropertyStore *pPS = nullptr;
119                                         if (SUCCEEDED(pShellLink->QueryInterface(IID_IPropertyStore, (void **)&pPS)))
120                                         {
121                                                 PROPVARIANT pv;
122                                                 if (SUCCEEDED(pPS->GetValue(PKEY_Title, &pv)))
123                                                 {
124                                                         list.push_back(Item(ucr::toTString(szPath), ucr::toTString(szArguments), ucr::toTString(pv.bstrVal), ucr::toTString(szDescription)));
125                                                         PropVariantClear(&pv);
126                                                 }
127                                                 pPS->Release();
128                                         }
129                                         pShellLink->Release();
130                                 }
131                         }
132                 }
133                 pObjectArray->Release();
134         }
135         pDocumentLists->Release();
136         return list;
137 }
138
139 }