OSDN Git Service

Merge with stable
[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 #include <ObjBase.h>
10 #include <ShlObj.h>
11 #if _MSC_VER >= 1600
12 #include <propvarutil.h>
13 #include <propkey.h>
14 #endif
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 #if _MSC_VER >= 1600
26         IShellLinkW *pShellLink = NULL;
27         if (FAILED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
28                                     IID_IShellLinkW, (void **)&pShellLink)))
29                 return NULL;
30
31         std::wstring app_path2(app_path);
32         if (app_path.empty())
33         {
34                 if (g_exe_path[0] == '\0')
35                         GetModuleFileNameW(NULL, g_exe_path, sizeof(g_exe_path)/sizeof(g_exe_path[0]));
36                 app_path2 = g_exe_path;
37         }
38         pShellLink->SetPath(app_path2.c_str());
39         pShellLink->SetIconLocation(app_path2.c_str(), icon_index);
40         pShellLink->SetArguments(params.c_str());
41         pShellLink->SetDescription(desc.c_str());
42
43         IPropertyStore *pPS = NULL;
44         if (SUCCEEDED(pShellLink->QueryInterface(IID_IPropertyStore, (void **)&pPS)))
45         {
46                 PROPVARIANT pv;
47                 InitPropVariantFromString(title.c_str(), &pv);
48                 pPS->SetValue(PKEY_Title, pv);
49                 PropVariantClear(&pv);
50                 pPS->Commit();
51                 pPS->Release();
52         }
53
54         return pShellLink;
55 #else
56         return NULL;
57 #endif
58 }
59
60 }
61
62 namespace JumpList
63 {
64
65 bool SetCurrentProcessExplicitAppUserModelID(const std::wstring& appid)
66 {
67         g_appid = appid;
68         HMODULE hLibrary = GetModuleHandle(_T("shell32.dll"));
69         if (!hLibrary)
70                 return false;
71         HRESULT (__stdcall *pfnSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID) = 
72                 (HRESULT (__stdcall *)(PCWSTR))GetProcAddress(hLibrary, "SetCurrentProcessExplicitAppUserModelID");
73         if (!pfnSetCurrentProcessExplicitAppUserModelID)
74                 return false;
75         return pfnSetCurrentProcessExplicitAppUserModelID(appid.c_str()) == S_OK;
76 }
77
78 bool AddToRecentDocs(const String& app_path, const String& params, const String& title, const String& desc, int icon_index)
79 {
80 #if _MSC_VER >= 1600
81         SHARDAPPIDINFOLINK saiil;
82         saiil.pszAppID = g_appid.c_str();
83 #ifdef _UNICODE
84         saiil.psl = CreateShellLink(app_path, params, title, desc, icon_index);
85 #else
86         saiil.psl = (IShellLink *)CreateShellLink(ucr::toUTF16(app_path), ucr::toUTF16(params), ucr::toUTF16(title), ucr::toUTF16(desc), icon_index);
87 #endif
88         if (!saiil.psl)
89                 return false;
90         SHAddToRecentDocs(SHARD_APPIDINFOLINK, &saiil);
91         saiil.psl->Release();
92         return true;
93 #else
94         return false;
95 #endif
96 }
97
98 std::vector<Item> GetRecentDocs(size_t nMaxItems)
99 {
100         std::vector<Item> list;
101 #if _MSC_VER >= 1600
102         IApplicationDocumentLists *pDocumentLists = NULL;
103         if (FAILED(CoCreateInstance(CLSID_ApplicationDocumentLists, NULL, CLSCTX_INPROC_SERVER,
104                                     IID_IApplicationDocumentLists, (void **)&pDocumentLists)))
105                 return list;
106         pDocumentLists->SetAppID(g_appid.c_str());
107
108         IObjectArray *pObjectArray;
109         if (SUCCEEDED(pDocumentLists->GetList(ADLT_RECENT, static_cast<UINT>(nMaxItems), IID_IObjectArray, (void **)&pObjectArray)))
110         {
111                 UINT nObjects;
112                 pObjectArray->GetCount(&nObjects);
113                 for (UINT i = 0; i < nObjects; ++i)
114                 {
115                         IShellLinkW *pShellLink;
116                         if (SUCCEEDED(pObjectArray->GetAt(i, IID_IShellLinkW, (void **)&pShellLink)))
117                         {
118                                 wchar_t szPath[MAX_PATH];
119                                 wchar_t szDescription[MAX_PATH];
120                                 wchar_t szArguments[MAX_PATH * 6];
121                                 pShellLink->GetPath(szPath, sizeof(szPath)/sizeof(szPath[0]), NULL, SLGP_RAWPATH);
122                                 pShellLink->GetDescription(szDescription, sizeof(szDescription)/sizeof(szDescription[0]));
123                                 pShellLink->GetArguments(szArguments, sizeof(szArguments)/sizeof(szArguments[0]));
124                                 IPropertyStore *pPS = NULL;
125                                 PROPVARIANT pv;
126                                 InitPropVariantFromString(L"", &pv);
127                                 if (SUCCEEDED(pShellLink->QueryInterface(IID_IPropertyStore, (void **)&pPS)))
128                                 {
129                                         pPS->GetValue(PKEY_Title, &pv);
130                                         pPS->Release();
131                                 }
132                                 list.push_back(Item(ucr::toTString(szPath), ucr::toTString(szArguments), ucr::toTString(pv.bstrVal), ucr::toTString(szDescription)));
133                                 PropVariantClear(&pv);
134                                 pShellLink->Release();
135                         }               
136                 }
137                 pObjectArray->Release();
138         }
139         pDocumentLists->Release();
140 #endif
141         return list;
142 }
143
144 }