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.

566 lines
10 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. shortcut.c
  5. Abstract:
  6. This module contains code to manipulate shortcuts.
  7. Author:
  8. Wesley Witt (wesw) 24-Jul-1997
  9. Revision History:
  10. --*/
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <shlobj.h>
  15. #include <shellapi.h>
  16. #include <commdlg.h>
  17. #include <winspool.h>
  18. #include <tchar.h>
  19. #include "faxreg.h"
  20. #include "faxutil.h"
  21. //
  22. // Cover page filename extension and link filename extension
  23. //
  24. #define CP_FILENAME_EXT TEXT(".cov")
  25. #define LNK_FILENAME_EXT TEXT(".lnk")
  26. #define FILENAME_EXT TEXT('.')
  27. #define MAX_FILENAME_EXT 4
  28. //
  29. // Whether not we've done OLE initialization
  30. //
  31. static BOOL oleInitialized = FALSE;
  32. //
  33. // Find the filename portion given a filename:
  34. // return a pointer to the '.' character if successful
  35. // NULL if there is no extension
  36. //
  37. #define FindFilenameExtension(pFilename) _tcsrchr(pFilename, FILENAME_EXT)
  38. static LPTSTR Platforms[] =
  39. {
  40. TEXT("Windows NT x86"),
  41. TEXT("Windows NT R4000"),
  42. TEXT("Windows NT Alpha_AXP"),
  43. TEXT("Windows NT PowerPC")
  44. };
  45. VOID
  46. InitOle(
  47. VOID
  48. )
  49. /*++
  50. Routine Description:
  51. Perform OLE initialization if necessary
  52. Arguments:
  53. NONE
  54. Return Value:
  55. NONE
  56. --*/
  57. {
  58. if (!oleInitialized) {
  59. HRESULT hResult = CoInitialize(NULL);
  60. if (hResult == S_OK || hResult == S_FALSE) {
  61. oleInitialized = TRUE;
  62. } else {
  63. DebugPrint(( TEXT("OLE initialization failed: %d\n"), hResult ));
  64. }
  65. }
  66. }
  67. VOID
  68. DeinitOle(
  69. VOID
  70. )
  71. /*++
  72. Routine Description:
  73. Perform OLE deinitialization if necessary
  74. Arguments:
  75. NONE
  76. Return Value:
  77. NONE
  78. --*/
  79. {
  80. if (oleInitialized) {
  81. CoUninitialize();
  82. }
  83. }
  84. BOOL
  85. ResolveShortcut(
  86. LPTSTR pLinkName,
  87. LPTSTR pFileName
  88. )
  89. /*++
  90. Routine Description:
  91. Resolve a shortcut to find the destination file
  92. Arguments:
  93. pLinkName - Specifies the name of a link file
  94. pFileName - Points to a buffer for storing the destination filename
  95. Return Value:
  96. TRUE if successful, FALSE otherwise
  97. --*/
  98. {
  99. LPTSTR pExtension;
  100. HRESULT hResult;
  101. IShellLink *pShellLink;
  102. IPersistFile *pPersistFile;
  103. #ifndef UNICODE
  104. LPWSTR pLinkNameW;
  105. #endif
  106. //
  107. // Default to empty string in case of an error
  108. //
  109. *pFileName = 0;
  110. if (!oleInitialized) {
  111. InitOle();
  112. if (!oleInitialized) {
  113. DebugPrint(( TEXT("OLE wasn't initialized successfully\n") ));
  114. return FALSE;
  115. }
  116. }
  117. //
  118. // Make sure the filename has the .LNK extension
  119. //
  120. if ((pExtension = FindFilenameExtension(pLinkName)) == NULL ||
  121. _tcsicmp(pExtension, LNK_FILENAME_EXT) != 0)
  122. {
  123. return FALSE;
  124. }
  125. //
  126. // Get a pointer to IShellLink interface
  127. //
  128. hResult = CoCreateInstance(&CLSID_ShellLink,
  129. NULL,
  130. CLSCTX_INPROC_SERVER,
  131. &IID_IShellLink,
  132. &pShellLink);
  133. if (SUCCEEDED(hResult)) {
  134. //
  135. // Get a pointer to IPersistFile interface
  136. //
  137. hResult = pShellLink->lpVtbl->QueryInterface(pShellLink,
  138. &IID_IPersistFile,
  139. &pPersistFile);
  140. if (SUCCEEDED(hResult)) {
  141. //
  142. // Now resolve the link to find the actually file it refers to
  143. //
  144. #ifdef UNICODE
  145. hResult = pPersistFile->lpVtbl->Load(pPersistFile, pLinkName, STGM_READ);
  146. #else
  147. pLinkNameW = AnsiStringToUnicodeString( pLinkName );
  148. hResult = pPersistFile->lpVtbl->Load(pPersistFile, pLinkNameW, STGM_READ);
  149. MemFree( pLinkNameW );
  150. #endif
  151. if (SUCCEEDED(hResult)) {
  152. hResult = pShellLink->lpVtbl->Resolve(pShellLink, NULL, SLR_NO_UI | 0x00010000);
  153. if (SUCCEEDED(hResult))
  154. pShellLink->lpVtbl->GetPath(pShellLink, pFileName, MAX_PATH, NULL, 0);
  155. }
  156. pPersistFile->lpVtbl->Release(pPersistFile);
  157. }
  158. pShellLink->lpVtbl->Release(pShellLink);
  159. }
  160. return SUCCEEDED(hResult);
  161. }
  162. BOOL
  163. CreateShortcut(
  164. LPTSTR pLinkName,
  165. LPTSTR pFileName
  166. )
  167. /*++
  168. Routine Description:
  169. Create a shortcut from pLinkName to pFileName
  170. Arguments:
  171. pLinkName - Name of the link file
  172. pFileName - Name of the destination file
  173. Return Value:
  174. TRUE if successful, FALSE otherwise
  175. --*/
  176. {
  177. HRESULT hResult;
  178. IShellLink *pShellLink;
  179. IPersistFile *pPersistFile;
  180. #ifndef UNICODE
  181. LPWSTR pLinkNameW;
  182. #endif
  183. if (!oleInitialized) {
  184. InitOle();
  185. if (!oleInitialized) {
  186. DebugPrint(( TEXT("OLE wasn't initialized successfully\n") ));
  187. return FALSE;
  188. }
  189. }
  190. hResult = CoCreateInstance(&CLSID_ShellLink,
  191. NULL,
  192. CLSCTX_INPROC_SERVER,
  193. &IID_IShellLink,
  194. &pShellLink);
  195. if (SUCCEEDED(hResult)) {
  196. hResult = pShellLink->lpVtbl->QueryInterface(pShellLink,
  197. &IID_IPersistFile,
  198. &pPersistFile);
  199. if (SUCCEEDED(hResult)) {
  200. pShellLink->lpVtbl->SetPath(pShellLink, pFileName);
  201. #ifdef UNICODE
  202. hResult = pPersistFile->lpVtbl->Save(pPersistFile, pLinkName, STGM_READ);
  203. #else
  204. pLinkNameW = AnsiStringToUnicodeString( pLinkName );
  205. hResult = pPersistFile->lpVtbl->Save(pPersistFile, pLinkNameW, STGM_READ);
  206. MemFree( pLinkNameW );
  207. #endif
  208. pPersistFile->lpVtbl->Release(pPersistFile);
  209. }
  210. pShellLink->lpVtbl->Release(pShellLink);
  211. }
  212. return SUCCEEDED(hResult);
  213. }
  214. BOOL
  215. IsCoverPageShortcut(
  216. LPCTSTR pLinkName
  217. )
  218. /*++
  219. Routine Description:
  220. Check if a link is a shortcut to some cover page file
  221. Arguments:
  222. pLinkName - Specifies the name of a link file
  223. Return Value:
  224. TRUE if the link file is a shortcut to a cover page file
  225. FALSE otherwise
  226. --*/
  227. {
  228. LPTSTR pExtension;
  229. TCHAR filename[MAX_PATH];
  230. //
  231. // Resolve the link if necessary and check if the final filename has
  232. // the properly extension.
  233. //
  234. return ResolveShortcut((LPTSTR)pLinkName, filename) &&
  235. (pExtension = FindFilenameExtension(filename)) &&
  236. _tcsicmp(pExtension, CP_FILENAME_EXT) == 0;
  237. }
  238. BOOL GetSpecialPath(
  239. int nFolder,
  240. LPTSTR Path
  241. )
  242. /*++
  243. Routine Description:
  244. Get a path from a CSIDL constant
  245. Arguments:
  246. nFolder - CSIDL_ constant
  247. Path - Buffer to receive the path, assume this buffer is at least MAX_PATH+1 chars large
  248. Return Value:
  249. TRUE for success.
  250. FALSE for failure.
  251. --*/
  252. {
  253. HRESULT hr;
  254. LPITEMIDLIST pIdl = NULL;
  255. LPMALLOC IMalloc = NULL;
  256. BOOL fSuccess = FALSE;
  257. hr = SHGetMalloc(&IMalloc);
  258. if (FAILED(hr) ) {
  259. DebugPrint(( TEXT("SHGetMalloc() failed, ec = %x\n"),hr));
  260. goto exit;
  261. }
  262. hr = SHGetSpecialFolderLocation (NULL,
  263. nFolder,
  264. &pIdl);
  265. if (FAILED(hr) ) {
  266. DebugPrint((TEXT("SHGetSpecialFolderLocation(%d) failed, ec = %x\n"),nFolder,hr));
  267. goto exit;
  268. }
  269. hr = SHGetPathFromIDList(pIdl, Path);
  270. if (FAILED(hr) ) {
  271. DebugPrint((TEXT("SHGetPAthFromIDList() failed, ec = %x\n"),hr));
  272. goto exit;
  273. }
  274. fSuccess = TRUE;
  275. exit:
  276. if (IMalloc && pIdl) {
  277. IMalloc->lpVtbl->Free(IMalloc, (void *) pIdl );
  278. }
  279. if (IMalloc) {
  280. IMalloc->lpVtbl->Release(IMalloc) ;
  281. }
  282. return fSuccess;
  283. }
  284. BOOL
  285. GetClientCpDir(
  286. LPTSTR CpDir,
  287. DWORD CpDirSize
  288. )
  289. /*++
  290. Routine Description:
  291. Gets the client coverpage directory.
  292. Arguments:
  293. CpDir - buffer to hold the coverpage dir
  294. CpDirSize - size in bytes of CpDir
  295. Return Value:
  296. Pointer to the client coverpage direcory.
  297. --*/
  298. {
  299. HKEY hKey;
  300. LONG rVal;
  301. DWORD RegType;
  302. TCHAR PartialPathBuffer[MAX_PATH];
  303. DWORD dwSize = sizeof(PartialPathBuffer);
  304. if (!GetSpecialPath(CSIDL_PERSONAL, CpDir )) {
  305. return FALSE;
  306. }
  307. rVal = RegOpenKey(
  308. HKEY_CURRENT_USER,
  309. REGKEY_FAX_SETUP,
  310. &hKey
  311. );
  312. if (rVal != ERROR_SUCCESS) {
  313. return FALSE;
  314. }
  315. rVal = RegQueryValueEx(
  316. hKey,
  317. REGVAL_CP_LOCATION,
  318. 0,
  319. &RegType,
  320. (LPBYTE) PartialPathBuffer,
  321. &dwSize
  322. );
  323. if (rVal != ERROR_SUCCESS) {
  324. RegCloseKey( hKey );
  325. return FALSE;
  326. }
  327. RegCloseKey( hKey );
  328. if (PartialPathBuffer[0] && PartialPathBuffer[_tcslen(PartialPathBuffer)-1] != TEXT('\\')) {
  329. _tcscat( PartialPathBuffer, TEXT("\\") );
  330. }
  331. ConcatenatePaths(CpDir, PartialPathBuffer);
  332. //
  333. // make sure that directory exists
  334. //
  335. MakeDirectory(CpDir);
  336. return TRUE;
  337. }
  338. BOOL
  339. GetServerCpDir(
  340. LPCTSTR ServerName OPTIONAL,
  341. LPTSTR CpDir,
  342. DWORD CpDirSize
  343. )
  344. /*++
  345. Routine Description:
  346. Gets the server coverpage directory.
  347. Arguments:
  348. ServerName - server name or NULL
  349. CpDir - buffer to hold the coverpage dir
  350. CpDirSize - size in bytes of CpDir
  351. Return Value:
  352. Pointer to the server coverpage direcory.
  353. --*/
  354. {
  355. TCHAR tmpcp[MAX_PATH];
  356. #undef IDS_COVERPAGE_DIR
  357. #define IDS_COVERPAGE_DIR 627
  358. if (!CpDir) {
  359. return(FALSE);
  360. }
  361. if (ServerName) {
  362. wsprintf( tmpcp, TEXT("\\\\%s\\coverpg$"),ServerName);
  363. } else {
  364. HINSTANCE hResource;
  365. TCHAR ResourceDll[MAX_PATH];
  366. TCHAR RestofPath[MAX_PATH];
  367. if (!GetSpecialPath(CSIDL_COMMON_DOCUMENTS, tmpcp )) {
  368. return(FALSE);
  369. }
  370. ExpandEnvironmentStrings(TEXT("%systemroot%\\system32\\faxocm.dll"),ResourceDll,sizeof(ResourceDll)/sizeof(TCHAR));
  371. hResource = LoadLibraryEx( ResourceDll, 0, LOAD_LIBRARY_AS_DATAFILE );
  372. if (!hResource) {
  373. return(FALSE);
  374. }
  375. if (!MyLoadString(hResource,IDS_COVERPAGE_DIR,RestofPath,sizeof(RestofPath)/sizeof(TCHAR),GetSystemDefaultUILanguage())) {
  376. FreeLibrary( hResource );
  377. return(FALSE);
  378. }
  379. ConcatenatePaths(tmpcp, RestofPath);
  380. FreeLibrary( hResource );
  381. }
  382. if ((DWORD) lstrlen(tmpcp) + 1 > CpDirSize) {
  383. return FALSE;
  384. }
  385. lstrcpy( CpDir,tmpcp ) ;
  386. return(TRUE);
  387. }