Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
7.6 KiB

  1. // blesslnk.cpp : Program to bless a LNK file with darwin descriptor
  2. // or logo3 app name/id
  3. #include <tchar.h>
  4. #include <stdio.h>
  5. #include <windows.h>
  6. #include <shlobj.h>
  7. #include <shlguidp.h>
  8. #include <shlwapi.h>
  9. #include "cdfsubs.hpp"
  10. #include "resource.h"
  11. #define FAIL_ARGS 1
  12. #define FAIL_OLE 2
  13. #define FAIL_LOAD 3
  14. #define FAIL_ENTRY 4
  15. #define FAIL_REG 5
  16. #define FAIL_SHELL 6
  17. #define DARWIN_ID 0x1
  18. #define LOGO3_ID 0x2
  19. // The following strings are used to support the shell link set path feature that
  20. // allows us to bless links for Darwin or Logo3 publising support in IE4
  21. #define DARWINGUID_TAG TEXT("::{9db1186e-40df-11d1-aa8c-00c04fb67863}:")
  22. #define DARWIN_TAG_LEN (ARRAYSIZE(DARWINGUID_TAG)-1)
  23. #define LOGO3GUID_TAG TEXT("::{9db1186f-40df-11d1-aa8c-00c04fb67863}:")
  24. #define LOGO3_TAG_LEN (ARRAYSIZE(LOGO3GUID_TAG)-1)
  25. // checking for shell32 4.72.2106.0 or greater
  26. #define IE401_SHELL_MAJOR 0x0004
  27. #define IE401_SHELL_MINOR 0x48
  28. #define IE401_SHELL_BUILD 0x083a
  29. BOOL IE401ShellAvailable()
  30. {
  31. BOOL bCanBlessLink = FALSE;
  32. DLLGETVERSIONPROC lpfnVersionProc = NULL;
  33. DLLVERSIONINFO dlinfo;
  34. HMODULE hMod = LoadLibrary("shell32.dll");
  35. if (hMod) {
  36. if ( (lpfnVersionProc = (DLLGETVERSIONPROC)GetProcAddress(hMod,"DllGetVersion")) )
  37. {
  38. dlinfo.cbSize = sizeof(DLLVERSIONINFO);
  39. if ( (lpfnVersionProc(&dlinfo) == S_OK) &&
  40. (dlinfo.dwMajorVersion > IE401_SHELL_MAJOR) ||
  41. ((dlinfo.dwMajorVersion == IE401_SHELL_MAJOR) &&
  42. (dlinfo.dwMinorVersion >= IE401_SHELL_MINOR)
  43. ))
  44. {
  45. bCanBlessLink = TRUE;
  46. if (dlinfo.dwMajorVersion == IE401_SHELL_MAJOR &&
  47. dlinfo.dwMinorVersion == IE401_SHELL_MINOR &&
  48. dlinfo.dwBuildNumber < IE401_SHELL_BUILD)
  49. {
  50. bCanBlessLink = FALSE;
  51. }
  52. }
  53. }
  54. }
  55. if (hMod)
  56. FreeLibrary(hMod);
  57. return bCanBlessLink;
  58. }
  59. HRESULT SetLnkBlessing( IShellLink *pishl, DWORD dwSig, LPSTR szBlessing )
  60. {
  61. HRESULT hr = S_OK;
  62. char szPath[MAX_PATH*4];
  63. char szTarget[MAX_PATH];
  64. if (dwSig == DARWIN_ID) {
  65. lstrcpy(szPath, DARWINGUID_TAG);
  66. } else if (dwSig == LOGO3_ID) {
  67. lstrcpy(szPath, LOGO3GUID_TAG);
  68. }else {
  69. hr = E_INVALIDARG;
  70. }
  71. if (SUCCEEDED(hr)) {
  72. lstrcat(szPath, szBlessing);
  73. lstrcat(szPath, "::");
  74. // get real target
  75. hr = pishl->GetPath(szTarget, MAX_PATH, NULL,0);
  76. // copy real target name
  77. if (SUCCEEDED(hr)) {
  78. lstrcat(szPath, szTarget);
  79. hr = pishl->SetPath( szPath );
  80. }
  81. }
  82. return hr;
  83. }
  84. int __cdecl main(int argc, char * argv[])
  85. {
  86. int iReturn = 0;
  87. HRESULT hr = S_OK;
  88. LPSTR pszLnkName = NULL;
  89. LPSTR pszLogo3ID = NULL;
  90. LPSTR pszDarwinID = NULL;
  91. LPSTR pszCDFURL = NULL;
  92. LPSTR pszTok;
  93. IPersistFile *pipfLnk = NULL;
  94. // Parse command line arguments.
  95. int iTok;
  96. for (iTok = 1; iTok < argc; iTok++)
  97. {
  98. pszTok = argv[iTok];
  99. if ((pszTok[0] == '-') || (pszTok[0] == '/'))
  100. {
  101. switch (pszTok[1])
  102. {
  103. case 'c':
  104. case 'C':
  105. pszCDFURL = argv[iTok+1];
  106. iTok++;
  107. break;
  108. case 'l':
  109. case 'L':
  110. pszLogo3ID = argv[iTok+1];
  111. iTok++;
  112. break;
  113. case 'd':
  114. case 'D':
  115. pszDarwinID = argv[iTok+1];
  116. iTok++;
  117. break;
  118. case '?':
  119. 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" );
  120. break;
  121. default:
  122. fprintf(stderr, "err - unrecognized flag: %s\n", pszTok);
  123. return FAIL_ARGS;
  124. }
  125. }
  126. else
  127. {
  128. if (pszLnkName == NULL)
  129. {
  130. pszLnkName = pszTok;
  131. break;
  132. }
  133. else
  134. {
  135. fprintf(stderr, "err - extra argument: %s\n", pszTok);
  136. return FAIL_ARGS;
  137. }
  138. }
  139. }
  140. if (pszLnkName == NULL)
  141. {
  142. fprintf(stderr, "err - no lnk file specified\n" );
  143. return FAIL_ARGS;
  144. }
  145. if (!IE401ShellAvailable())
  146. {
  147. fprintf(stderr, "err - Need to have IE401 shell enabled for this feature.\n" );
  148. return FAIL_SHELL;
  149. }
  150. // Initialize OLE.
  151. if (FAILED(CoInitialize(NULL)))
  152. {
  153. return FAIL_OLE;
  154. }
  155. if ( SUCCEEDED(hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IPersistFile, (LPVOID*)&pipfLnk)) )
  156. {
  157. WCHAR szwLnkName[MAX_PATH];
  158. MultiByteToWideChar( CP_ACP, 0, pszLnkName, -1, szwLnkName, MAX_PATH );
  159. if ( SUCCEEDED(hr = pipfLnk->Load(szwLnkName, STGM_READ)) )
  160. {
  161. IShellLink *pishl = NULL;
  162. if ( SUCCEEDED(hr = pipfLnk->QueryInterface(IID_IShellLink, (LPVOID*)&pishl)) )
  163. {
  164. if ( pszLogo3ID )
  165. {
  166. if ( FAILED(hr = SetLnkBlessing( pishl, LOGO3_ID, pszLogo3ID )) )
  167. fprintf( stderr, "err - failed to bless %s with Logo3-ID %s\n", pszLnkName, pszLogo3ID );
  168. }
  169. if ( pszDarwinID )
  170. {
  171. if ( FAILED(hr = SetLnkBlessing(pishl, DARWIN_ID, pszDarwinID)) )
  172. fprintf( stderr, "err - failed to bless %s with Darwin-ID %s\n", pszLnkName, pszDarwinID );
  173. }
  174. }
  175. if ( SUCCEEDED(hr) )
  176. hr = pipfLnk->Save( NULL, FALSE );
  177. if ( FAILED(hr) )
  178. fprintf( stderr, "err - failed with error %lx\n", hr );
  179. }
  180. pipfLnk->Release();
  181. }
  182. if (pszCDFURL && SUCCEEDED(hr)) {
  183. // FEATURE: pszLogo3ID is passed instead of a friendly name. In
  184. // the future, we can add another switch to blesslnk to accomodate
  185. // this. Also, we must subscribe with UI (non-silent mode) because
  186. // subscribing will not work properly otherwise.
  187. SubscribeChannel(NULL, pszLogo3ID, pszCDFURL, FALSE);
  188. }
  189. CoUninitialize();
  190. return iReturn;
  191. }