diff -r 000000000000 -r 6474c204b198 browser/metro/shell/linktool/linktool.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/browser/metro/shell/linktool/linktool.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,296 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#undef WINVER +#undef _WIN32_WINNT +#define WINVER 0x602 +#define _WIN32_WINNT 0x602 + +#include +#include +#include +#include +#include +#define INITGUID +#include +#include +#include + +// Indicates that an application supports dual desktop and immersive modes. In Windows 8, this property is only applicable for web browsers. +//DEFINE_PROPERTYKEY(PKEY_AppUserModel_IsDualMode, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 11); + +void DumpParameters(LPCWSTR aTargetPath, LPCWSTR aShortcutPath, LPCWSTR aAppModelID, LPCWSTR aDescription) +{ + if (aTargetPath) + wprintf(L"target path: '%s'\n", aTargetPath); + if (aShortcutPath) + wprintf(L"shortcut path: '%s'\n", aShortcutPath); + if (aAppModelID) + wprintf(L"app id: '%s'\n", aAppModelID); + if (aDescription) + wprintf(L"description: '%s'\n", aDescription); +} + +HRESULT +SetShortcutProps(LPCWSTR aShortcutPath, LPCWSTR aAppModelID, bool aSetID, bool aSetMode) +{ + HRESULT hres; + ::CoInitialize(nullptr); + + IPropertyStore *m_pps = nullptr; + if (FAILED(hres = SHGetPropertyStoreFromParsingName(aShortcutPath, + nullptr, + GPS_READWRITE, + IID_PPV_ARGS(&m_pps)))) { + printf("SHGetPropertyStoreFromParsingName failed\n"); + goto Exit; + } + + if (aSetMode) { + PROPVARIANT propvar; + if (FAILED(hres = InitPropVariantFromBoolean(true, &propvar)) || + FAILED(hres = m_pps->SetValue(PKEY_AppUserModel_IsDualMode, propvar))) { + goto Exit; + } + PropVariantClear(&propvar); + } + + if (aSetID && aAppModelID) { + PROPVARIANT propvar; + if (FAILED(hres = InitPropVariantFromString(aAppModelID, &propvar)) || + FAILED(hres = m_pps->SetValue(PKEY_AppUserModel_ID, propvar))) { + goto Exit; + } + PropVariantClear(&propvar); + } + + hres = m_pps->Commit(); + + Exit: + + if (m_pps) { + m_pps->Release(); + } + + CoUninitialize(); + return hres; +} + +HRESULT +PrintShortcutProps(LPCWSTR aTargetPath) +{ + HRESULT hres; + ::CoInitialize(nullptr); + + IPropertyStore *m_pps = nullptr; + if (FAILED(hres = SHGetPropertyStoreFromParsingName(aTargetPath, + nullptr, + GPS_READWRITE, + IID_PPV_ARGS(&m_pps)))) { + printf("SHGetPropertyStoreFromParsingName failed\n"); + goto Exit; + } + + bool found = false; + + PROPVARIANT propvar; + if (SUCCEEDED(hres = m_pps->GetValue(PKEY_AppUserModel_IsDualMode, &propvar)) && propvar.vt == VT_BOOL && propvar.boolVal == -1) { + printf("PKEY_AppUserModel_IsDualMode found\n"); + PropVariantClear(&propvar); + found = true; + } + + if (SUCCEEDED(hres = m_pps->GetValue(PKEY_AppUserModel_ID, &propvar)) && propvar.pwszVal) { + printf("PKEY_AppUserModel_ID found "); + wprintf(L"value: '%s'\n", propvar.pwszVal); + PropVariantClear(&propvar); + found = true; + } + + if (!found) { + printf("no known properties found.\n"); + } + + Exit: + + if (m_pps) { + m_pps->Release(); + } + + CoUninitialize(); + return hres; +} + +HRESULT +CreateLink(LPCWSTR aTargetPath, LPCWSTR aShortcutPath, LPCWSTR aDescription) +{ + HRESULT hres; + IShellLink* psl; + + wprintf(L"creating shortcut: '%s'\n", aShortcutPath); + + CoInitialize(nullptr); + + hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, + IID_IShellLink, (LPVOID*)&psl); + if (FAILED(hres)) { + CoUninitialize(); + return hres; + } + psl->SetPath(aTargetPath); + if (aDescription) { + psl->SetDescription(aDescription); + } else { + psl->SetDescription(L""); + } + + IPersistFile* ppf = nullptr; + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); + + if (SUCCEEDED(hres)) { + hres = ppf->Save(aShortcutPath, TRUE); + ppf->Release(); + } + psl->Release(); + CoUninitialize(); + return hres; +} + +void DumpCommands() +{ + printf("control options:\n"); + printf(" /CREATE create a shortcut for the target file.\n"); + printf(" /UPDATE update properties on the target file.\n"); + printf(" /PRINT print the known properties set on the target file.\n"); + printf("parameters:\n"); + printf(" /T(path) the full path and filename of the target file.\n"); + printf(" /S(path) with CREATE, the full path and filename of the shortcut to create.\n"); + printf(" /D(string) with CREATE, adds a description to the shortcut.\n"); + printf(" /A(id) the app model id to assign to the shortcut or target file.\n"); + printf(" /M enable support for dual desktop and immersive modes on the shortcut or target file.\n"); +} + +int wmain(int argc, WCHAR* argv[]) +{ + WCHAR shortcutPathStr[MAX_PATH]; + WCHAR targetPathStr[MAX_PATH]; + WCHAR appModelIDStr[MAX_PATH]; + WCHAR descriptionStr[MAX_PATH]; + + shortcutPathStr[0] = '\0'; + targetPathStr[0] = '\0'; + appModelIDStr[0] = '\0'; + descriptionStr[0] = '\0'; + + bool createShortcutFound = false; + bool updateFound = false; + bool shortcutPathFound = false; + bool targetPathFound = false; + bool appModelIDFound = false; + bool modeFound = false; + bool descriptionFound = false; + bool printFound = false; + + int idx; + for (idx = 1; idx < argc; idx++) { + if (!wcscmp(L"/CREATE", argv[idx])) { + createShortcutFound = true; + continue; + } + if (!wcscmp(L"/UPDATE", argv[idx])) { + updateFound = true; + continue; + } + if (!wcscmp(L"/PRINT", argv[idx])) { + printFound = true; + continue; + } + + if (!wcsncmp(L"/S", argv[idx], 2) && wcslen(argv[idx]) > 2) { + wcscpy_s(shortcutPathStr, MAX_PATH, (argv[idx]+2)); + shortcutPathFound = true; + continue; + } + if (!wcsncmp(L"/T", argv[idx], 2) && wcslen(argv[idx]) > 2) { + wcscpy_s(targetPathStr, MAX_PATH, (argv[idx]+2)); + targetPathFound = true; + continue; + } + if (!wcsncmp(L"/A", argv[idx], 2) && wcslen(argv[idx]) > 2) { + wcscpy_s(appModelIDStr, MAX_PATH, (argv[idx]+2)); + appModelIDFound = true; + continue; + } + if (!wcsncmp(L"/D", argv[idx], 2) && wcslen(argv[idx]) > 2 && wcslen(argv[idx]) < MAX_PATH) { + wcscpy_s(descriptionStr, MAX_PATH, (argv[idx]+2)); + descriptionFound = true; + continue; + } + if (!wcscmp(L"/M", argv[idx])) { + modeFound = true; + continue; + } + } + + DumpParameters(targetPathStr, shortcutPathStr, appModelIDStr, descriptionStr); + + if (!createShortcutFound && !updateFound && !printFound) { + DumpCommands(); + return 0; + } + + if (!targetPathFound) { + printf("missing target file path.\n"); + return -1; + } + + HRESULT hres; + + if (printFound) { + if (FAILED(hres = PrintShortcutProps(targetPathStr))) { + printf("failed printing target props HRESULT=%X\n", hres); + return -1; + } + return 0; + } + + if (createShortcutFound && !shortcutPathFound) { + printf("missing shortcut file path.\n"); + return -1; + } + + if (updateFound && !appModelIDFound && !modeFound) { + printf("no properties selected.\n"); + return -1; + } + + if (createShortcutFound) { + if (FAILED(hres = CreateLink(targetPathStr, + shortcutPathStr, + (descriptionFound ? descriptionStr : nullptr)))) { + printf("failed creating shortcut HRESULT=%X\n", hres); + return -1; + } + } + + LPCWSTR target; + if (createShortcutFound) { + target = shortcutPathStr; + } else { + target = targetPathStr; + } + + if (appModelIDFound || modeFound) { + if (FAILED(hres = SetShortcutProps(target, + (appModelIDFound ? appModelIDStr : nullptr), + appModelIDFound, modeFound))) { + printf("failed adding property HRESULT=%X\n", hres); + return -1; + } + } + + return 0; +} +