255 lines
7.6 KiB
C++
255 lines
7.6 KiB
C++
// 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;
|
|
}
|