OSDN Git Service

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