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.

298 lines
6.8 KiB

  1. #include <pch.cxx>
  2. #pragma hdrstop
  3. #include <ole2.h>
  4. #include <windows.h>
  5. #include <shlobj.h>
  6. #include <shlguid.h>
  7. #define TRKDATA_ALLOCATE
  8. #include "trkwks.hxx"
  9. DWORD g_Debug = 0;
  10. void Usage()
  11. {
  12. wprintf( L"\n"
  13. L"Purpose: Create/resolve shell links\n"
  14. L"Usage: tshlink <-c <link client> <link source>> | <-r <link client>>\n"
  15. L"E.g.: tshlink -c myfile.txt.lnk myfile.txt\n"
  16. L" tshlink -r myfile.txt.lnk\n" );
  17. exit(0);
  18. }
  19. class CMyApp
  20. {
  21. public:
  22. CMyApp()
  23. {
  24. m_hwnd = NULL;
  25. *m_szAppName = '\0';
  26. m_nCmdShow = 0;
  27. }
  28. ~CMyApp() {}
  29. public:
  30. __declspec(dllexport)
  31. static long FAR PASCAL
  32. WndProc (HWND hwnd, UINT message, UINT wParam, LONG lParam);
  33. BOOL Init( HANDLE hInstance, HANDLE hPrevInstance,
  34. LPSTR lpszCmdLine, int nCmdShow,
  35. int cArg, TCHAR *rgtszArg[] );
  36. WORD Run( void );
  37. private:
  38. static HWND m_hwnd;
  39. static CHAR m_szAppName[80];
  40. static HINSTANCE m_hInstance;
  41. static int m_nCmdShow;
  42. static int m_cArg;
  43. static TCHAR ** m_rgtszArg;
  44. };
  45. HWND CMyApp::m_hwnd;
  46. CHAR CMyApp::m_szAppName[80];
  47. HINSTANCE CMyApp::m_hInstance;
  48. int CMyApp::m_nCmdShow;
  49. int CMyApp::m_cArg;
  50. TCHAR ** CMyApp::m_rgtszArg;
  51. CMyApp cMyApp;
  52. EXTERN_C void __cdecl _tmain( int cArg, TCHAR *rgtszArg[] )
  53. {
  54. if( cMyApp.Init(NULL, NULL, //hInstance, hPrevInstance,
  55. NULL, SW_SHOWNORMAL, //lpszCmdLine, nCmdShow) )
  56. cArg, rgtszArg ))
  57. {
  58. cMyApp.Run();
  59. }
  60. }
  61. void ShellLink( HWND hwnd, int cArg, TCHAR *rgtszArg[] );
  62. long FAR PASCAL
  63. CMyApp::WndProc (HWND hwnd, UINT message,
  64. UINT wParam, LONG lParam)
  65. {
  66. switch (message)
  67. {
  68. case WM_CREATE:
  69. ShellLink( hwnd, m_cArg, m_rgtszArg );
  70. PostQuitMessage(0);
  71. break;
  72. case WM_CLOSE :
  73. DestroyWindow( hwnd );
  74. break;
  75. case WM_DESTROY :
  76. PostQuitMessage (0) ;
  77. return 0 ;
  78. }
  79. return DefWindowProc (hwnd, message, wParam, lParam) ;
  80. }
  81. BOOL
  82. CMyApp::Init( HANDLE hInstance, HANDLE hPrevInstance,
  83. LPSTR lpszCmdLine, int nCmdShow,
  84. int cArg, TCHAR *rgtszArg[] )
  85. {
  86. WNDCLASSA wndclass;
  87. sprintf( m_szAppName, "ShellLink" );
  88. m_hInstance = (HINSTANCE) hInstance;
  89. m_nCmdShow = nCmdShow;
  90. m_cArg = cArg;
  91. m_rgtszArg = rgtszArg;
  92. if( !hPrevInstance )
  93. {
  94. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  95. wndclass.lpfnWndProc = CMyApp::WndProc;
  96. wndclass.cbClsExtra = 0;
  97. wndclass.cbWndExtra = 0;
  98. wndclass.hInstance = m_hInstance;
  99. wndclass.hIcon = LoadIconA( m_hInstance, m_szAppName );
  100. wndclass.hCursor = LoadCursorA( NULL, MAKEINTRESOURCEA(32512) ); // IDC_ARROW
  101. wndclass.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH );
  102. wndclass.lpszMenuName = NULL;
  103. wndclass.lpszClassName = m_szAppName;
  104. RegisterClassA( &wndclass );
  105. }
  106. return( TRUE ); // Successful
  107. }
  108. #ifdef CreateWindowA
  109. #undef CreateWindow
  110. #endif
  111. WORD
  112. CMyApp::Run( void )
  113. {
  114. MSG msg;
  115. HRESULT hr;
  116. CHAR szErrorMessage[80];
  117. msg.wParam = 0;
  118. m_hwnd = CreateWindowA( m_szAppName,
  119. "ShellLink",
  120. WS_OVERLAPPEDWINDOW,
  121. CW_USEDEFAULT, CW_USEDEFAULT,
  122. CW_USEDEFAULT, CW_USEDEFAULT,
  123. NULL, NULL, m_hInstance, NULL );
  124. if( NULL == m_hwnd )
  125. {
  126. sprintf( szErrorMessage, "Failed CreateWindowA (%lu)", GetLastError() );
  127. goto Exit;
  128. }
  129. ShowWindow( m_hwnd, SW_MINIMIZE );
  130. UpdateWindow( m_hwnd );
  131. while( GetMessage( &msg, NULL, 0, 0 ))
  132. {
  133. TranslateMessage(&msg);
  134. DispatchMessage(&msg);
  135. }
  136. Exit:
  137. return( msg.wParam );
  138. }
  139. void ShellLink( HWND hwnd, int cArg, TCHAR *rgtszArg[] )
  140. {
  141. HRESULT hr;
  142. IPersistFile *ppf = NULL;
  143. IShellLink *psl = NULL;
  144. TCHAR tszPath[ MAX_PATH + 1 ];
  145. TCHAR tszDir[ MAX_PATH + 1 ];
  146. WIN32_FIND_DATA fd;
  147. DWORD dwFlags;
  148. try
  149. {
  150. if( 2 > cArg ) Usage();
  151. if( L'-' != rgtszArg[1][0] ) Usage();
  152. hr = CoInitialize( NULL );
  153. if( FAILED(hr) ) throw L"Failed CoInit";
  154. hr = CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**) &psl );
  155. if( FAILED(hr) ) throw L"Failed CoCreateInstance";
  156. hr = psl->QueryInterface( IID_IPersistFile, (void**) &ppf );
  157. if( FAILED(hr) ) throw L"Failed QI for IPersistFile";
  158. switch( rgtszArg[1][1] )
  159. {
  160. case L'c':
  161. case L'C':
  162. if( 4 > cArg ) Usage();
  163. if( L':' == rgtszArg[3][1]
  164. ||
  165. !wcsncmp( L"\\\\", rgtszArg[3], 2 ))
  166. {
  167. if( L':' == rgtszArg[3][1] && L'\\' != rgtszArg[3][2] )
  168. Usage();
  169. wcscpy( tszPath, rgtszArg[3] );
  170. wcscpy( tszDir, tszPath );
  171. TCHAR *ptsz = wcsrchr( tszDir, L'\\' );
  172. *ptsz = L'\0';
  173. }
  174. else
  175. {
  176. if( !GetCurrentDirectory( sizeof(tszDir), tszDir ))
  177. {
  178. hr = HRESULT_FROM_WIN32(GetLastError());
  179. throw L"Failed GetCurrentDirectory";
  180. }
  181. wcscpy( tszPath, tszDir );
  182. wcscat( tszPath, L"\\" );
  183. wcscat( tszPath, rgtszArg[3] );
  184. }
  185. hr = psl->SetPath( tszPath );
  186. if( FAILED(hr) ) throw L"Failed IShellLink::SetPath";
  187. hr = psl->SetWorkingDirectory( tszDir );
  188. if( FAILED(hr) ) throw L"Failed IShellLink::SetWorkingDirectory";
  189. hr = ppf->Save( rgtszArg[2], TRUE );
  190. if( FAILED(hr) ) throw L"Failed IPersistFile::Save";
  191. wprintf( L"Success\n" );
  192. break;
  193. case L'r':
  194. case L'R':
  195. if( 3 > cArg ) Usage();
  196. hr = ppf->Load( rgtszArg[2], STGM_READ );
  197. if( FAILED(hr) ) throw L"Failed IPersistFile::Load";
  198. dwFlags = (180*1000 << 16) | SLR_ANY_MATCH;
  199. hr = psl->Resolve( hwnd, dwFlags );
  200. if( FAILED(hr) ) throw L"Failed Resolve";
  201. hr = psl->GetPath( tszPath, sizeof(tszPath), &fd, 0 );
  202. if( FAILED(hr) ) throw L"Failed IShellLink::GetPath";
  203. wprintf( L"Path = \"%s\"\n", tszPath );
  204. break;
  205. default:
  206. Usage();
  207. break;
  208. } // switch
  209. }
  210. catch( TCHAR *tszError )
  211. {
  212. wprintf( L"Error: %s (%08x)\n", tszError, hr );
  213. }
  214. if( ppf ) ppf->Release();
  215. if( psl ) psl->Release();
  216. }