Leaked source code of windows server 2003
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.

336 lines
9.6 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // link.c link management routines (reading, etc.)
  4. //
  5. // Copyright (c) 1985 - 1999, Microsoft Corporation
  6. //
  7. //---------------------------------------------------------------------------
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. DWORD
  11. GetTitleFromLinkName(
  12. IN LPWSTR szLinkName,
  13. OUT LPWSTR szTitle
  14. )
  15. /*++
  16. Routine Description:
  17. This routine returns the title (i.e., display name of the link) in szTitle,
  18. and the number of bytes (not chars) in szTitle.
  19. Arguments:
  20. szLinkName - fully qualified path to link file
  21. szTitle - pointer to buffer to contain title (display name) of the link
  22. i.e.:
  23. "C:\nt\desktop\A Link File Name.lnk" --> "A Link File Name"
  24. Return Value:
  25. number of bytes copied to szTitle
  26. --*/
  27. {
  28. DWORD dwLen;
  29. LPWSTR pLnk, pDot;
  30. LPWSTR pPath = szLinkName;
  31. ASSERT(szLinkName);
  32. // find filename at end of fully qualified link name and point pLnk to it
  33. for (pLnk = pPath; *pPath; pPath++)
  34. {
  35. if ( (pPath[0] == L'\\' || pPath[0] == L':') &&
  36. pPath[1] &&
  37. (pPath[1] != L'\\')
  38. )
  39. pLnk = pPath + 1;
  40. }
  41. // find extension (.lnk)
  42. pPath = pLnk;
  43. for (pDot = NULL; *pPath; pPath++)
  44. {
  45. switch (*pPath) {
  46. case L'.':
  47. pDot = pPath; // remember the last dot
  48. break;
  49. case L'\\':
  50. case L' ': // extensions can't have spaces
  51. pDot = NULL; // forget last dot, it was in a directory
  52. break;
  53. }
  54. }
  55. // if we found the extension, pDot points to it, if not, pDot
  56. // is NULL.
  57. if (pDot)
  58. {
  59. dwLen = (ULONG)((pDot - pLnk) * sizeof(WCHAR));
  60. }
  61. else
  62. {
  63. dwLen = lstrlenW(pLnk) * sizeof(WCHAR);
  64. }
  65. dwLen = min(dwLen, MAX_TITLE_LENGTH);
  66. RtlCopyMemory(szTitle, pLnk, dwLen);
  67. return dwLen;
  68. }
  69. BOOL ReadString( HANDLE hFile, LPVOID * lpVoid, BOOL bUnicode )
  70. {
  71. USHORT cch;
  72. DWORD dwBytesRead;
  73. BOOL fResult = TRUE;
  74. if (bUnicode)
  75. {
  76. LPWSTR lpWStr;
  77. fResult &= ReadFile( hFile, (LPVOID)&cch, sizeof(cch), &dwBytesRead, NULL );
  78. lpWStr = ConsoleHeapAlloc(HEAP_ZERO_MEMORY, (cch + 1) * sizeof(WCHAR));
  79. if (lpWStr) {
  80. fResult &= ReadFile( hFile, (LPVOID)lpWStr, cch*sizeof(WCHAR), &dwBytesRead, NULL );
  81. lpWStr[cch] = L'\0';
  82. }
  83. *(LPWSTR *)lpVoid = lpWStr;
  84. } else {
  85. LPSTR lpStr;
  86. fResult &= ReadFile( hFile, (LPVOID)&cch, sizeof(cch), &dwBytesRead, NULL );
  87. lpStr = ConsoleHeapAlloc(HEAP_ZERO_MEMORY, cch + 1);
  88. if (lpStr) {
  89. fResult &= ReadFile( hFile, (LPVOID)lpStr, cch, &dwBytesRead, NULL );
  90. lpStr[cch] = '\0';
  91. }
  92. *(LPSTR *)lpVoid = lpStr;
  93. }
  94. return fResult;
  95. }
  96. BOOL LoadLink( LPWSTR pszLinkName, CShellLink * this )
  97. {
  98. HANDLE hFile;
  99. DWORD dwBytesRead, cbSize, cbTotal, cbToRead;
  100. BOOL fResult = TRUE;
  101. LPSTR pTemp = NULL;
  102. // Try to open the file
  103. hFile = CreateFile(pszLinkName,
  104. GENERIC_READ,
  105. FILE_SHARE_READ,
  106. NULL,
  107. OPEN_EXISTING,
  108. FILE_ATTRIBUTE_NORMAL,
  109. NULL);
  110. if (hFile == INVALID_HANDLE_VALUE) {
  111. return FALSE;
  112. }
  113. // Now, read out data...
  114. fResult = ReadFile( hFile, (LPVOID)&this->sld, sizeof(this->sld), &dwBytesRead, NULL );
  115. fResult &= ((dwBytesRead == sizeof(this->sld)) && (this->sld.cbSize == sizeof(this->sld)));
  116. if (!fResult) {
  117. // This is a bad .lnk file. Bail.
  118. goto ErrorExit;
  119. }
  120. // read all of the members
  121. if (this->sld.dwFlags & SLDF_HAS_ID_LIST)
  122. {
  123. // Read the size of the IDLIST
  124. cbSize = 0; // need to zero out to get HIWORD 0 'cause USHORT is only 2 bytes
  125. fResult &= ReadFile( hFile, (LPVOID)&cbSize, sizeof(USHORT), &dwBytesRead, NULL );
  126. fResult &= (dwBytesRead == sizeof(USHORT));
  127. if (cbSize)
  128. {
  129. fResult &=
  130. (SetFilePointer(hFile,cbSize,NULL,FILE_CURRENT)!=0xFFFFFFFF);
  131. }
  132. else
  133. {
  134. goto ErrorExit;
  135. }
  136. }
  137. if (this->sld.dwFlags & (SLDF_HAS_LINK_INFO))
  138. {
  139. fResult &= ReadFile( hFile, (LPVOID)&cbSize, sizeof(cbSize), &dwBytesRead, NULL );
  140. fResult &= (dwBytesRead == sizeof(cbSize));
  141. if (cbSize >= sizeof(cbSize))
  142. {
  143. cbSize -= sizeof(cbSize);
  144. fResult &=
  145. (SetFilePointer(hFile,cbSize,NULL,FILE_CURRENT)!=0xFFFFFFFF);
  146. }
  147. }
  148. if (this->sld.dwFlags & SLDF_HAS_NAME)
  149. fResult &= ReadString( hFile, &this->pszName, this->sld.dwFlags & SLDF_UNICODE);
  150. if (this->sld.dwFlags & SLDF_HAS_RELPATH)
  151. fResult &= ReadString( hFile, &this->pszRelPath, this->sld.dwFlags & SLDF_UNICODE);
  152. if (this->sld.dwFlags & SLDF_HAS_WORKINGDIR)
  153. fResult &= ReadString( hFile, &this->pszWorkingDir, this->sld.dwFlags & SLDF_UNICODE);
  154. if (this->sld.dwFlags & SLDF_HAS_ARGS)
  155. fResult &= ReadString( hFile, &this->pszArgs, this->sld.dwFlags & SLDF_UNICODE);
  156. if (this->sld.dwFlags & SLDF_HAS_ICONLOCATION)
  157. fResult &= ReadString( hFile, &this->pszIconLocation, this->sld.dwFlags & SLDF_UNICODE);
  158. // Read in extra data sections
  159. this->pExtraData = NULL;
  160. cbTotal = 0;
  161. while (TRUE)
  162. {
  163. LPSTR pReadData = NULL;
  164. cbSize = 0;
  165. fResult &= ReadFile( hFile, (LPVOID)&cbSize, sizeof(cbSize), &dwBytesRead, NULL );
  166. if (cbSize < sizeof(cbSize))
  167. break;
  168. if (pTemp)
  169. {
  170. pTemp = (void *)ConsoleHeapReAlloc(
  171. HEAP_ZERO_MEMORY,
  172. this->pExtraData,
  173. cbTotal + cbSize + sizeof(DWORD)
  174. );
  175. if (pTemp)
  176. {
  177. this->pExtraData = pTemp;
  178. }
  179. }
  180. else
  181. {
  182. this->pExtraData = pTemp = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, cbTotal + cbSize + sizeof(DWORD) );
  183. }
  184. if (!pTemp)
  185. break;
  186. cbToRead = cbSize - sizeof(cbSize);
  187. pReadData = pTemp + cbTotal;
  188. fResult &= ReadFile( hFile, (LPVOID)(pReadData + sizeof(cbSize)), cbToRead, &dwBytesRead, NULL );
  189. if (dwBytesRead == cbToRead) {
  190. // got all of the extra data, comit it
  191. *((UNALIGNED DWORD *)pReadData) = cbSize;
  192. cbTotal += cbSize;
  193. } else {
  194. break;
  195. }
  196. }
  197. ErrorExit:
  198. CloseHandle( hFile );
  199. return fResult;
  200. }
  201. DWORD GetLinkProperties( LPWSTR pszLinkName, LPVOID lpvBuffer, UINT cb )
  202. {
  203. CShellLink mld;
  204. DWORD fResult;
  205. LPNT_CONSOLE_PROPS lpExtraData;
  206. DWORD dwSize = 0;
  207. // Zero out structure on the stack
  208. RtlZeroMemory( &mld, sizeof(mld) );
  209. // Load link data
  210. if (!LoadLink( pszLinkName, &mld )) {
  211. RIPMSG1(RIP_WARNING, "LoadLink %ws failed", pszLinkName);
  212. fResult = LINK_NOINFO;
  213. goto Cleanup;
  214. }
  215. // Check return buffer -- is it big enough?
  216. ASSERT(cb >= sizeof( LNKPROPNTCONSOLE));
  217. // Zero out callers buffer
  218. RtlZeroMemory( lpvBuffer, cb );
  219. // Copy relevant shell link data into caller's buffer
  220. if (mld.pszName)
  221. lstrcpy( ((LPLNKPROPNTCONSOLE)lpvBuffer)->pszName, mld.pszName );
  222. if (mld.pszIconLocation)
  223. lstrcpy( ((LPLNKPROPNTCONSOLE)lpvBuffer)->pszIconLocation, mld.pszIconLocation );
  224. ((LPLNKPROPNTCONSOLE)lpvBuffer)->uIcon = mld.sld.iIcon;
  225. ((LPLNKPROPNTCONSOLE)lpvBuffer)->uShowCmd = mld.sld.iShowCmd;
  226. ((LPLNKPROPNTCONSOLE)lpvBuffer)->uHotKey = mld.sld.wHotkey;
  227. fResult = LINK_SIMPLEINFO;
  228. // Find console properties in extra data section
  229. for( lpExtraData = (LPNT_CONSOLE_PROPS)mld.pExtraData;
  230. lpExtraData && lpExtraData->cbSize;
  231. (LPBYTE)lpExtraData += dwSize
  232. )
  233. {
  234. dwSize = lpExtraData->cbSize;
  235. if (dwSize)
  236. {
  237. if (lpExtraData->dwSignature == NT_CONSOLE_PROPS_SIG)
  238. {
  239. RtlCopyMemory( &((LPLNKPROPNTCONSOLE)lpvBuffer)->console_props,
  240. lpExtraData,
  241. sizeof( NT_CONSOLE_PROPS )
  242. );
  243. fResult = LINK_FULLINFO;
  244. #if !defined(FE_SB)
  245. break;
  246. #endif
  247. }
  248. #if defined(FE_SB)
  249. if (lpExtraData->dwSignature == NT_FE_CONSOLE_PROPS_SIG)
  250. {
  251. LPNT_FE_CONSOLE_PROPS lpFEExtraData = (LPNT_FE_CONSOLE_PROPS)lpExtraData;
  252. RtlCopyMemory( &((LPLNKPROPNTCONSOLE)lpvBuffer)->fe_console_props,
  253. lpFEExtraData,
  254. sizeof( NT_FE_CONSOLE_PROPS )
  255. );
  256. }
  257. #endif
  258. }
  259. }
  260. Cleanup:
  261. if (mld.pszName)
  262. ConsoleHeapFree( mld.pszName );
  263. if (mld.pszRelPath)
  264. ConsoleHeapFree( mld.pszRelPath );
  265. if (mld.pszWorkingDir)
  266. ConsoleHeapFree( mld.pszWorkingDir );
  267. if (mld.pszArgs)
  268. ConsoleHeapFree( mld.pszArgs );
  269. if (mld.pszIconLocation)
  270. ConsoleHeapFree( mld.pszIconLocation );
  271. if (mld.pExtraData)
  272. ConsoleHeapFree( mld.pExtraData );
  273. return fResult;
  274. }