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

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

mercurial