1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/metro/shell/linktool/linktool.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,296 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#undef WINVER 1.10 +#undef _WIN32_WINNT 1.11 +#define WINVER 0x602 1.12 +#define _WIN32_WINNT 0x602 1.13 + 1.14 +#include <windows.h> 1.15 +#include <shobjidl.h> 1.16 +#include <objbase.h> 1.17 +#include <shlguid.h> 1.18 +#include <shlobj.h> 1.19 +#define INITGUID 1.20 +#include <propvarutil.h> 1.21 +#include <propkey.h> 1.22 +#include <stdio.h> 1.23 + 1.24 +// Indicates that an application supports dual desktop and immersive modes. In Windows 8, this property is only applicable for web browsers. 1.25 +//DEFINE_PROPERTYKEY(PKEY_AppUserModel_IsDualMode, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 11); 1.26 + 1.27 +void DumpParameters(LPCWSTR aTargetPath, LPCWSTR aShortcutPath, LPCWSTR aAppModelID, LPCWSTR aDescription) 1.28 +{ 1.29 + if (aTargetPath) 1.30 + wprintf(L"target path: '%s'\n", aTargetPath); 1.31 + if (aShortcutPath) 1.32 + wprintf(L"shortcut path: '%s'\n", aShortcutPath); 1.33 + if (aAppModelID) 1.34 + wprintf(L"app id: '%s'\n", aAppModelID); 1.35 + if (aDescription) 1.36 + wprintf(L"description: '%s'\n", aDescription); 1.37 +} 1.38 + 1.39 +HRESULT 1.40 +SetShortcutProps(LPCWSTR aShortcutPath, LPCWSTR aAppModelID, bool aSetID, bool aSetMode) 1.41 +{ 1.42 + HRESULT hres; 1.43 + ::CoInitialize(nullptr); 1.44 + 1.45 + IPropertyStore *m_pps = nullptr; 1.46 + if (FAILED(hres = SHGetPropertyStoreFromParsingName(aShortcutPath, 1.47 + nullptr, 1.48 + GPS_READWRITE, 1.49 + IID_PPV_ARGS(&m_pps)))) { 1.50 + printf("SHGetPropertyStoreFromParsingName failed\n"); 1.51 + goto Exit; 1.52 + } 1.53 + 1.54 + if (aSetMode) { 1.55 + PROPVARIANT propvar; 1.56 + if (FAILED(hres = InitPropVariantFromBoolean(true, &propvar)) || 1.57 + FAILED(hres = m_pps->SetValue(PKEY_AppUserModel_IsDualMode, propvar))) { 1.58 + goto Exit; 1.59 + } 1.60 + PropVariantClear(&propvar); 1.61 + } 1.62 + 1.63 + if (aSetID && aAppModelID) { 1.64 + PROPVARIANT propvar; 1.65 + if (FAILED(hres = InitPropVariantFromString(aAppModelID, &propvar)) || 1.66 + FAILED(hres = m_pps->SetValue(PKEY_AppUserModel_ID, propvar))) { 1.67 + goto Exit; 1.68 + } 1.69 + PropVariantClear(&propvar); 1.70 + } 1.71 + 1.72 + hres = m_pps->Commit(); 1.73 + 1.74 + Exit: 1.75 + 1.76 + if (m_pps) { 1.77 + m_pps->Release(); 1.78 + } 1.79 + 1.80 + CoUninitialize(); 1.81 + return hres; 1.82 +} 1.83 + 1.84 +HRESULT 1.85 +PrintShortcutProps(LPCWSTR aTargetPath) 1.86 +{ 1.87 + HRESULT hres; 1.88 + ::CoInitialize(nullptr); 1.89 + 1.90 + IPropertyStore *m_pps = nullptr; 1.91 + if (FAILED(hres = SHGetPropertyStoreFromParsingName(aTargetPath, 1.92 + nullptr, 1.93 + GPS_READWRITE, 1.94 + IID_PPV_ARGS(&m_pps)))) { 1.95 + printf("SHGetPropertyStoreFromParsingName failed\n"); 1.96 + goto Exit; 1.97 + } 1.98 + 1.99 + bool found = false; 1.100 + 1.101 + PROPVARIANT propvar; 1.102 + if (SUCCEEDED(hres = m_pps->GetValue(PKEY_AppUserModel_IsDualMode, &propvar)) && propvar.vt == VT_BOOL && propvar.boolVal == -1) { 1.103 + printf("PKEY_AppUserModel_IsDualMode found\n"); 1.104 + PropVariantClear(&propvar); 1.105 + found = true; 1.106 + } 1.107 + 1.108 + if (SUCCEEDED(hres = m_pps->GetValue(PKEY_AppUserModel_ID, &propvar)) && propvar.pwszVal) { 1.109 + printf("PKEY_AppUserModel_ID found "); 1.110 + wprintf(L"value: '%s'\n", propvar.pwszVal); 1.111 + PropVariantClear(&propvar); 1.112 + found = true; 1.113 + } 1.114 + 1.115 + if (!found) { 1.116 + printf("no known properties found.\n"); 1.117 + } 1.118 + 1.119 + Exit: 1.120 + 1.121 + if (m_pps) { 1.122 + m_pps->Release(); 1.123 + } 1.124 + 1.125 + CoUninitialize(); 1.126 + return hres; 1.127 +} 1.128 + 1.129 +HRESULT 1.130 +CreateLink(LPCWSTR aTargetPath, LPCWSTR aShortcutPath, LPCWSTR aDescription) 1.131 +{ 1.132 + HRESULT hres; 1.133 + IShellLink* psl; 1.134 + 1.135 + wprintf(L"creating shortcut: '%s'\n", aShortcutPath); 1.136 + 1.137 + CoInitialize(nullptr); 1.138 + 1.139 + hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, 1.140 + IID_IShellLink, (LPVOID*)&psl); 1.141 + if (FAILED(hres)) { 1.142 + CoUninitialize(); 1.143 + return hres; 1.144 + } 1.145 + psl->SetPath(aTargetPath); 1.146 + if (aDescription) { 1.147 + psl->SetDescription(aDescription); 1.148 + } else { 1.149 + psl->SetDescription(L""); 1.150 + } 1.151 + 1.152 + IPersistFile* ppf = nullptr; 1.153 + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); 1.154 + 1.155 + if (SUCCEEDED(hres)) { 1.156 + hres = ppf->Save(aShortcutPath, TRUE); 1.157 + ppf->Release(); 1.158 + } 1.159 + psl->Release(); 1.160 + CoUninitialize(); 1.161 + return hres; 1.162 +} 1.163 + 1.164 +void DumpCommands() 1.165 +{ 1.166 + printf("control options:\n"); 1.167 + printf(" /CREATE create a shortcut for the target file.\n"); 1.168 + printf(" /UPDATE update properties on the target file.\n"); 1.169 + printf(" /PRINT print the known properties set on the target file.\n"); 1.170 + printf("parameters:\n"); 1.171 + printf(" /T(path) the full path and filename of the target file.\n"); 1.172 + printf(" /S(path) with CREATE, the full path and filename of the shortcut to create.\n"); 1.173 + printf(" /D(string) with CREATE, adds a description to the shortcut.\n"); 1.174 + printf(" /A(id) the app model id to assign to the shortcut or target file.\n"); 1.175 + printf(" /M enable support for dual desktop and immersive modes on the shortcut or target file.\n"); 1.176 +} 1.177 + 1.178 +int wmain(int argc, WCHAR* argv[]) 1.179 +{ 1.180 + WCHAR shortcutPathStr[MAX_PATH]; 1.181 + WCHAR targetPathStr[MAX_PATH]; 1.182 + WCHAR appModelIDStr[MAX_PATH]; 1.183 + WCHAR descriptionStr[MAX_PATH]; 1.184 + 1.185 + shortcutPathStr[0] = '\0'; 1.186 + targetPathStr[0] = '\0'; 1.187 + appModelIDStr[0] = '\0'; 1.188 + descriptionStr[0] = '\0'; 1.189 + 1.190 + bool createShortcutFound = false; 1.191 + bool updateFound = false; 1.192 + bool shortcutPathFound = false; 1.193 + bool targetPathFound = false; 1.194 + bool appModelIDFound = false; 1.195 + bool modeFound = false; 1.196 + bool descriptionFound = false; 1.197 + bool printFound = false; 1.198 + 1.199 + int idx; 1.200 + for (idx = 1; idx < argc; idx++) { 1.201 + if (!wcscmp(L"/CREATE", argv[idx])) { 1.202 + createShortcutFound = true; 1.203 + continue; 1.204 + } 1.205 + if (!wcscmp(L"/UPDATE", argv[idx])) { 1.206 + updateFound = true; 1.207 + continue; 1.208 + } 1.209 + if (!wcscmp(L"/PRINT", argv[idx])) { 1.210 + printFound = true; 1.211 + continue; 1.212 + } 1.213 + 1.214 + if (!wcsncmp(L"/S", argv[idx], 2) && wcslen(argv[idx]) > 2) { 1.215 + wcscpy_s(shortcutPathStr, MAX_PATH, (argv[idx]+2)); 1.216 + shortcutPathFound = true; 1.217 + continue; 1.218 + } 1.219 + if (!wcsncmp(L"/T", argv[idx], 2) && wcslen(argv[idx]) > 2) { 1.220 + wcscpy_s(targetPathStr, MAX_PATH, (argv[idx]+2)); 1.221 + targetPathFound = true; 1.222 + continue; 1.223 + } 1.224 + if (!wcsncmp(L"/A", argv[idx], 2) && wcslen(argv[idx]) > 2) { 1.225 + wcscpy_s(appModelIDStr, MAX_PATH, (argv[idx]+2)); 1.226 + appModelIDFound = true; 1.227 + continue; 1.228 + } 1.229 + if (!wcsncmp(L"/D", argv[idx], 2) && wcslen(argv[idx]) > 2 && wcslen(argv[idx]) < MAX_PATH) { 1.230 + wcscpy_s(descriptionStr, MAX_PATH, (argv[idx]+2)); 1.231 + descriptionFound = true; 1.232 + continue; 1.233 + } 1.234 + if (!wcscmp(L"/M", argv[idx])) { 1.235 + modeFound = true; 1.236 + continue; 1.237 + } 1.238 + } 1.239 + 1.240 + DumpParameters(targetPathStr, shortcutPathStr, appModelIDStr, descriptionStr); 1.241 + 1.242 + if (!createShortcutFound && !updateFound && !printFound) { 1.243 + DumpCommands(); 1.244 + return 0; 1.245 + } 1.246 + 1.247 + if (!targetPathFound) { 1.248 + printf("missing target file path.\n"); 1.249 + return -1; 1.250 + } 1.251 + 1.252 + HRESULT hres; 1.253 + 1.254 + if (printFound) { 1.255 + if (FAILED(hres = PrintShortcutProps(targetPathStr))) { 1.256 + printf("failed printing target props HRESULT=%X\n", hres); 1.257 + return -1; 1.258 + } 1.259 + return 0; 1.260 + } 1.261 + 1.262 + if (createShortcutFound && !shortcutPathFound) { 1.263 + printf("missing shortcut file path.\n"); 1.264 + return -1; 1.265 + } 1.266 + 1.267 + if (updateFound && !appModelIDFound && !modeFound) { 1.268 + printf("no properties selected.\n"); 1.269 + return -1; 1.270 + } 1.271 + 1.272 + if (createShortcutFound) { 1.273 + if (FAILED(hres = CreateLink(targetPathStr, 1.274 + shortcutPathStr, 1.275 + (descriptionFound ? descriptionStr : nullptr)))) { 1.276 + printf("failed creating shortcut HRESULT=%X\n", hres); 1.277 + return -1; 1.278 + } 1.279 + } 1.280 + 1.281 + LPCWSTR target; 1.282 + if (createShortcutFound) { 1.283 + target = shortcutPathStr; 1.284 + } else { 1.285 + target = targetPathStr; 1.286 + } 1.287 + 1.288 + if (appModelIDFound || modeFound) { 1.289 + if (FAILED(hres = SetShortcutProps(target, 1.290 + (appModelIDFound ? appModelIDStr : nullptr), 1.291 + appModelIDFound, modeFound))) { 1.292 + printf("failed adding property HRESULT=%X\n", hres); 1.293 + return -1; 1.294 + } 1.295 + } 1.296 + 1.297 + return 0; 1.298 +} 1.299 +