browser/metro/shell/linktool/linktool.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #undef WINVER
michael@0 7 #undef _WIN32_WINNT
michael@0 8 #define WINVER 0x602
michael@0 9 #define _WIN32_WINNT 0x602
michael@0 10
michael@0 11 #include <windows.h>
michael@0 12 #include <shobjidl.h>
michael@0 13 #include <objbase.h>
michael@0 14 #include <shlguid.h>
michael@0 15 #include <shlobj.h>
michael@0 16 #define INITGUID
michael@0 17 #include <propvarutil.h>
michael@0 18 #include <propkey.h>
michael@0 19 #include <stdio.h>
michael@0 20
michael@0 21 // Indicates that an application supports dual desktop and immersive modes. In Windows 8, this property is only applicable for web browsers.
michael@0 22 //DEFINE_PROPERTYKEY(PKEY_AppUserModel_IsDualMode, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 11);
michael@0 23
michael@0 24 void DumpParameters(LPCWSTR aTargetPath, LPCWSTR aShortcutPath, LPCWSTR aAppModelID, LPCWSTR aDescription)
michael@0 25 {
michael@0 26 if (aTargetPath)
michael@0 27 wprintf(L"target path: '%s'\n", aTargetPath);
michael@0 28 if (aShortcutPath)
michael@0 29 wprintf(L"shortcut path: '%s'\n", aShortcutPath);
michael@0 30 if (aAppModelID)
michael@0 31 wprintf(L"app id: '%s'\n", aAppModelID);
michael@0 32 if (aDescription)
michael@0 33 wprintf(L"description: '%s'\n", aDescription);
michael@0 34 }
michael@0 35
michael@0 36 HRESULT
michael@0 37 SetShortcutProps(LPCWSTR aShortcutPath, LPCWSTR aAppModelID, bool aSetID, bool aSetMode)
michael@0 38 {
michael@0 39 HRESULT hres;
michael@0 40 ::CoInitialize(nullptr);
michael@0 41
michael@0 42 IPropertyStore *m_pps = nullptr;
michael@0 43 if (FAILED(hres = SHGetPropertyStoreFromParsingName(aShortcutPath,
michael@0 44 nullptr,
michael@0 45 GPS_READWRITE,
michael@0 46 IID_PPV_ARGS(&m_pps)))) {
michael@0 47 printf("SHGetPropertyStoreFromParsingName failed\n");
michael@0 48 goto Exit;
michael@0 49 }
michael@0 50
michael@0 51 if (aSetMode) {
michael@0 52 PROPVARIANT propvar;
michael@0 53 if (FAILED(hres = InitPropVariantFromBoolean(true, &propvar)) ||
michael@0 54 FAILED(hres = m_pps->SetValue(PKEY_AppUserModel_IsDualMode, propvar))) {
michael@0 55 goto Exit;
michael@0 56 }
michael@0 57 PropVariantClear(&propvar);
michael@0 58 }
michael@0 59
michael@0 60 if (aSetID && aAppModelID) {
michael@0 61 PROPVARIANT propvar;
michael@0 62 if (FAILED(hres = InitPropVariantFromString(aAppModelID, &propvar)) ||
michael@0 63 FAILED(hres = m_pps->SetValue(PKEY_AppUserModel_ID, propvar))) {
michael@0 64 goto Exit;
michael@0 65 }
michael@0 66 PropVariantClear(&propvar);
michael@0 67 }
michael@0 68
michael@0 69 hres = m_pps->Commit();
michael@0 70
michael@0 71 Exit:
michael@0 72
michael@0 73 if (m_pps) {
michael@0 74 m_pps->Release();
michael@0 75 }
michael@0 76
michael@0 77 CoUninitialize();
michael@0 78 return hres;
michael@0 79 }
michael@0 80
michael@0 81 HRESULT
michael@0 82 PrintShortcutProps(LPCWSTR aTargetPath)
michael@0 83 {
michael@0 84 HRESULT hres;
michael@0 85 ::CoInitialize(nullptr);
michael@0 86
michael@0 87 IPropertyStore *m_pps = nullptr;
michael@0 88 if (FAILED(hres = SHGetPropertyStoreFromParsingName(aTargetPath,
michael@0 89 nullptr,
michael@0 90 GPS_READWRITE,
michael@0 91 IID_PPV_ARGS(&m_pps)))) {
michael@0 92 printf("SHGetPropertyStoreFromParsingName failed\n");
michael@0 93 goto Exit;
michael@0 94 }
michael@0 95
michael@0 96 bool found = false;
michael@0 97
michael@0 98 PROPVARIANT propvar;
michael@0 99 if (SUCCEEDED(hres = m_pps->GetValue(PKEY_AppUserModel_IsDualMode, &propvar)) && propvar.vt == VT_BOOL && propvar.boolVal == -1) {
michael@0 100 printf("PKEY_AppUserModel_IsDualMode found\n");
michael@0 101 PropVariantClear(&propvar);
michael@0 102 found = true;
michael@0 103 }
michael@0 104
michael@0 105 if (SUCCEEDED(hres = m_pps->GetValue(PKEY_AppUserModel_ID, &propvar)) && propvar.pwszVal) {
michael@0 106 printf("PKEY_AppUserModel_ID found ");
michael@0 107 wprintf(L"value: '%s'\n", propvar.pwszVal);
michael@0 108 PropVariantClear(&propvar);
michael@0 109 found = true;
michael@0 110 }
michael@0 111
michael@0 112 if (!found) {
michael@0 113 printf("no known properties found.\n");
michael@0 114 }
michael@0 115
michael@0 116 Exit:
michael@0 117
michael@0 118 if (m_pps) {
michael@0 119 m_pps->Release();
michael@0 120 }
michael@0 121
michael@0 122 CoUninitialize();
michael@0 123 return hres;
michael@0 124 }
michael@0 125
michael@0 126 HRESULT
michael@0 127 CreateLink(LPCWSTR aTargetPath, LPCWSTR aShortcutPath, LPCWSTR aDescription)
michael@0 128 {
michael@0 129 HRESULT hres;
michael@0 130 IShellLink* psl;
michael@0 131
michael@0 132 wprintf(L"creating shortcut: '%s'\n", aShortcutPath);
michael@0 133
michael@0 134 CoInitialize(nullptr);
michael@0 135
michael@0 136 hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER,
michael@0 137 IID_IShellLink, (LPVOID*)&psl);
michael@0 138 if (FAILED(hres)) {
michael@0 139 CoUninitialize();
michael@0 140 return hres;
michael@0 141 }
michael@0 142 psl->SetPath(aTargetPath);
michael@0 143 if (aDescription) {
michael@0 144 psl->SetDescription(aDescription);
michael@0 145 } else {
michael@0 146 psl->SetDescription(L"");
michael@0 147 }
michael@0 148
michael@0 149 IPersistFile* ppf = nullptr;
michael@0 150 hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
michael@0 151
michael@0 152 if (SUCCEEDED(hres)) {
michael@0 153 hres = ppf->Save(aShortcutPath, TRUE);
michael@0 154 ppf->Release();
michael@0 155 }
michael@0 156 psl->Release();
michael@0 157 CoUninitialize();
michael@0 158 return hres;
michael@0 159 }
michael@0 160
michael@0 161 void DumpCommands()
michael@0 162 {
michael@0 163 printf("control options:\n");
michael@0 164 printf(" /CREATE create a shortcut for the target file.\n");
michael@0 165 printf(" /UPDATE update properties on the target file.\n");
michael@0 166 printf(" /PRINT print the known properties set on the target file.\n");
michael@0 167 printf("parameters:\n");
michael@0 168 printf(" /T(path) the full path and filename of the target file.\n");
michael@0 169 printf(" /S(path) with CREATE, the full path and filename of the shortcut to create.\n");
michael@0 170 printf(" /D(string) with CREATE, adds a description to the shortcut.\n");
michael@0 171 printf(" /A(id) the app model id to assign to the shortcut or target file.\n");
michael@0 172 printf(" /M enable support for dual desktop and immersive modes on the shortcut or target file.\n");
michael@0 173 }
michael@0 174
michael@0 175 int wmain(int argc, WCHAR* argv[])
michael@0 176 {
michael@0 177 WCHAR shortcutPathStr[MAX_PATH];
michael@0 178 WCHAR targetPathStr[MAX_PATH];
michael@0 179 WCHAR appModelIDStr[MAX_PATH];
michael@0 180 WCHAR descriptionStr[MAX_PATH];
michael@0 181
michael@0 182 shortcutPathStr[0] = '\0';
michael@0 183 targetPathStr[0] = '\0';
michael@0 184 appModelIDStr[0] = '\0';
michael@0 185 descriptionStr[0] = '\0';
michael@0 186
michael@0 187 bool createShortcutFound = false;
michael@0 188 bool updateFound = false;
michael@0 189 bool shortcutPathFound = false;
michael@0 190 bool targetPathFound = false;
michael@0 191 bool appModelIDFound = false;
michael@0 192 bool modeFound = false;
michael@0 193 bool descriptionFound = false;
michael@0 194 bool printFound = false;
michael@0 195
michael@0 196 int idx;
michael@0 197 for (idx = 1; idx < argc; idx++) {
michael@0 198 if (!wcscmp(L"/CREATE", argv[idx])) {
michael@0 199 createShortcutFound = true;
michael@0 200 continue;
michael@0 201 }
michael@0 202 if (!wcscmp(L"/UPDATE", argv[idx])) {
michael@0 203 updateFound = true;
michael@0 204 continue;
michael@0 205 }
michael@0 206 if (!wcscmp(L"/PRINT", argv[idx])) {
michael@0 207 printFound = true;
michael@0 208 continue;
michael@0 209 }
michael@0 210
michael@0 211 if (!wcsncmp(L"/S", argv[idx], 2) && wcslen(argv[idx]) > 2) {
michael@0 212 wcscpy_s(shortcutPathStr, MAX_PATH, (argv[idx]+2));
michael@0 213 shortcutPathFound = true;
michael@0 214 continue;
michael@0 215 }
michael@0 216 if (!wcsncmp(L"/T", argv[idx], 2) && wcslen(argv[idx]) > 2) {
michael@0 217 wcscpy_s(targetPathStr, MAX_PATH, (argv[idx]+2));
michael@0 218 targetPathFound = true;
michael@0 219 continue;
michael@0 220 }
michael@0 221 if (!wcsncmp(L"/A", argv[idx], 2) && wcslen(argv[idx]) > 2) {
michael@0 222 wcscpy_s(appModelIDStr, MAX_PATH, (argv[idx]+2));
michael@0 223 appModelIDFound = true;
michael@0 224 continue;
michael@0 225 }
michael@0 226 if (!wcsncmp(L"/D", argv[idx], 2) && wcslen(argv[idx]) > 2 && wcslen(argv[idx]) < MAX_PATH) {
michael@0 227 wcscpy_s(descriptionStr, MAX_PATH, (argv[idx]+2));
michael@0 228 descriptionFound = true;
michael@0 229 continue;
michael@0 230 }
michael@0 231 if (!wcscmp(L"/M", argv[idx])) {
michael@0 232 modeFound = true;
michael@0 233 continue;
michael@0 234 }
michael@0 235 }
michael@0 236
michael@0 237 DumpParameters(targetPathStr, shortcutPathStr, appModelIDStr, descriptionStr);
michael@0 238
michael@0 239 if (!createShortcutFound && !updateFound && !printFound) {
michael@0 240 DumpCommands();
michael@0 241 return 0;
michael@0 242 }
michael@0 243
michael@0 244 if (!targetPathFound) {
michael@0 245 printf("missing target file path.\n");
michael@0 246 return -1;
michael@0 247 }
michael@0 248
michael@0 249 HRESULT hres;
michael@0 250
michael@0 251 if (printFound) {
michael@0 252 if (FAILED(hres = PrintShortcutProps(targetPathStr))) {
michael@0 253 printf("failed printing target props HRESULT=%X\n", hres);
michael@0 254 return -1;
michael@0 255 }
michael@0 256 return 0;
michael@0 257 }
michael@0 258
michael@0 259 if (createShortcutFound && !shortcutPathFound) {
michael@0 260 printf("missing shortcut file path.\n");
michael@0 261 return -1;
michael@0 262 }
michael@0 263
michael@0 264 if (updateFound && !appModelIDFound && !modeFound) {
michael@0 265 printf("no properties selected.\n");
michael@0 266 return -1;
michael@0 267 }
michael@0 268
michael@0 269 if (createShortcutFound) {
michael@0 270 if (FAILED(hres = CreateLink(targetPathStr,
michael@0 271 shortcutPathStr,
michael@0 272 (descriptionFound ? descriptionStr : nullptr)))) {
michael@0 273 printf("failed creating shortcut HRESULT=%X\n", hres);
michael@0 274 return -1;
michael@0 275 }
michael@0 276 }
michael@0 277
michael@0 278 LPCWSTR target;
michael@0 279 if (createShortcutFound) {
michael@0 280 target = shortcutPathStr;
michael@0 281 } else {
michael@0 282 target = targetPathStr;
michael@0 283 }
michael@0 284
michael@0 285 if (appModelIDFound || modeFound) {
michael@0 286 if (FAILED(hres = SetShortcutProps(target,
michael@0 287 (appModelIDFound ? appModelIDStr : nullptr),
michael@0 288 appModelIDFound, modeFound))) {
michael@0 289 printf("failed adding property HRESULT=%X\n", hres);
michael@0 290 return -1;
michael@0 291 }
michael@0 292 }
michael@0 293
michael@0 294 return 0;
michael@0 295 }
michael@0 296

mercurial