// blesslnk.cpp : Program to bless a LNK file with darwin descriptor // or logo3 app name/id #include #include #include #include #include #include #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; }