|
|
// blesslnk.cpp : Program to bless a LNK file with darwin descriptor
// or logo3 app name/id
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <shlobj.h>
#include <shlguidp.h>
#include <shlwapi.h>
#include "cdfsubs.hpp"
#include "resource.h"
#define FAIL_ARGS 1
#define FAIL_OLE 2
#define FAIL_LOAD 3
#define FAIL_ENTRY 4
#define FAIL_REG 5
#define FAIL_SHELL 6
#define DARWIN_ID 0x1
#define LOGO3_ID 0x2
// The following strings are used to support the shell link set path feature that
// allows us to bless links for Darwin or Logo3 publising support in IE4
#define DARWINGUID_TAG TEXT("::{9db1186e-40df-11d1-aa8c-00c04fb67863}:")
#define DARWIN_TAG_LEN (ARRAYSIZE(DARWINGUID_TAG)-1)
#define LOGO3GUID_TAG TEXT("::{9db1186f-40df-11d1-aa8c-00c04fb67863}:")
#define LOGO3_TAG_LEN (ARRAYSIZE(LOGO3GUID_TAG)-1)
// checking for shell32 4.72.2106.0 or greater
#define IE401_SHELL_MAJOR 0x0004
#define IE401_SHELL_MINOR 0x48
#define IE401_SHELL_BUILD 0x083a
BOOL IE401ShellAvailable() { BOOL bCanBlessLink = FALSE; DLLGETVERSIONPROC lpfnVersionProc = NULL; DLLVERSIONINFO dlinfo;
HMODULE hMod = LoadLibrary("shell32.dll");
if (hMod) {
if ( (lpfnVersionProc = (DLLGETVERSIONPROC)GetProcAddress(hMod,"DllGetVersion")) ) {
dlinfo.cbSize = sizeof(DLLVERSIONINFO);
if ( (lpfnVersionProc(&dlinfo) == S_OK) &&
(dlinfo.dwMajorVersion > IE401_SHELL_MAJOR) || ((dlinfo.dwMajorVersion == IE401_SHELL_MAJOR) && (dlinfo.dwMinorVersion >= IE401_SHELL_MINOR) ))
{ bCanBlessLink = TRUE; if (dlinfo.dwMajorVersion == IE401_SHELL_MAJOR && dlinfo.dwMinorVersion == IE401_SHELL_MINOR && dlinfo.dwBuildNumber < IE401_SHELL_BUILD) { bCanBlessLink = FALSE; } } } }
if (hMod) FreeLibrary(hMod);
return bCanBlessLink; }
HRESULT SetLnkBlessing( IShellLink *pishl, DWORD dwSig, LPSTR szBlessing ) { HRESULT hr = S_OK; char szPath[MAX_PATH*4]; char szTarget[MAX_PATH];
if (dwSig == DARWIN_ID) { lstrcpy(szPath, DARWINGUID_TAG); } else if (dwSig == LOGO3_ID) { lstrcpy(szPath, LOGO3GUID_TAG); }else { hr = E_INVALIDARG; }
if (SUCCEEDED(hr)) {
lstrcat(szPath, szBlessing);
lstrcat(szPath, "::");
// get real target
hr = pishl->GetPath(szTarget, MAX_PATH, NULL,0);
// copy real target name
if (SUCCEEDED(hr)) { lstrcat(szPath, szTarget);
hr = pishl->SetPath( szPath ); } }
return hr; }
int __cdecl main(int argc, char * argv[]) { int iReturn = 0; HRESULT hr = S_OK; LPSTR pszLnkName = NULL; LPSTR pszLogo3ID = NULL; LPSTR pszDarwinID = NULL; LPSTR pszCDFURL = NULL; LPSTR pszTok; IPersistFile *pipfLnk = NULL;
// Parse command line arguments.
int iTok; for (iTok = 1; iTok < argc; iTok++) { pszTok = argv[iTok]; if ((pszTok[0] == '-') || (pszTok[0] == '/')) { switch (pszTok[1]) { case 'c': case 'C': pszCDFURL = argv[iTok+1]; iTok++; break;
case 'l': case 'L': pszLogo3ID = argv[iTok+1]; iTok++; break; case 'd': case 'D': pszDarwinID = argv[iTok+1]; iTok++; break; case '?': fprintf(stderr, "\nUsage: blesslnk [/l Logo3-ID] [/d Darwin-ID] lnkname\n/l - bless for Logo3 Application Channel notifcation.\n/d - bless for Darwin\n" ); break;
default: fprintf(stderr, "err - unrecognized flag: %s\n", pszTok); return FAIL_ARGS; } } else { if (pszLnkName == NULL) { pszLnkName = pszTok; break; } else { fprintf(stderr, "err - extra argument: %s\n", pszTok); return FAIL_ARGS; } } }
if (pszLnkName == NULL) { fprintf(stderr, "err - no lnk file specified\n" ); return FAIL_ARGS; }
if (!IE401ShellAvailable()) { fprintf(stderr, "err - Need to have IE401 shell enabled for this feature.\n" ); return FAIL_SHELL; }
// Initialize OLE.
if (FAILED(CoInitialize(NULL))) { return FAIL_OLE; }
if ( SUCCEEDED(hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IPersistFile, (LPVOID*)&pipfLnk)) ) { WCHAR szwLnkName[MAX_PATH];
MultiByteToWideChar( CP_ACP, 0, pszLnkName, -1, szwLnkName, MAX_PATH );
if ( SUCCEEDED(hr = pipfLnk->Load(szwLnkName, STGM_READ)) ) {
IShellLink *pishl = NULL;
if ( SUCCEEDED(hr = pipfLnk->QueryInterface(IID_IShellLink, (LPVOID*)&pishl)) ) { if ( pszLogo3ID ) { if ( FAILED(hr = SetLnkBlessing( pishl, LOGO3_ID, pszLogo3ID )) ) fprintf( stderr, "err - failed to bless %s with Logo3-ID %s\n", pszLnkName, pszLogo3ID ); }
if ( pszDarwinID ) { if ( FAILED(hr = SetLnkBlessing(pishl, DARWIN_ID, pszDarwinID)) ) fprintf( stderr, "err - failed to bless %s with Darwin-ID %s\n", pszLnkName, pszDarwinID ); }
}
if ( SUCCEEDED(hr) ) hr = pipfLnk->Save( NULL, FALSE );
if ( FAILED(hr) ) fprintf( stderr, "err - failed with error %lx\n", hr );
}
pipfLnk->Release(); }
if (pszCDFURL && SUCCEEDED(hr)) {
// FEATURE: pszLogo3ID is passed instead of a friendly name. In
// the future, we can add another switch to blesslnk to accomodate
// this. Also, we must subscribe with UI (non-silent mode) because
// subscribing will not work properly otherwise.
SubscribeChannel(NULL, pszLogo3ID, pszCDFURL, FALSE); }
CoUninitialize(); return iReturn; }
|