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.

469 lines
14 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name: instcon.cxx
  4. Abstract:
  5. Installed container class derived from URL_CONTAINER
  6. Author:
  7. Adriaan Canter (adriaanc) 04-10-97
  8. --*/
  9. #include <cache.hxx>
  10. #define HTTP_OK "HTTP/1.0 200 OK\r\n\r\n"
  11. /*--------------------- CInstCon Public Functions-----------------------------*/
  12. /*-----------------------------------------------------------------------------
  13. CInstCon::CInstCon
  14. -----------------------------------------------------------------------------*/
  15. CInstCon::CInstCon(LPSTR CacheName, LPSTR VolumeLabel, LPSTR VolumeTitle,
  16. LPSTR CachePath, LPSTR CachePrefix, LPSTR PrefixMap,
  17. LONGLONG CacheLimit, DWORD dwOptions)
  18. : URL_CONTAINER(CacheName, CachePath, CachePrefix, CacheLimit, dwOptions)
  19. {
  20. if (_Status != ERROR_SUCCESS)
  21. {
  22. INET_ASSERT(FALSE);
  23. return;
  24. }
  25. _szVolumeLabel = NewString(VolumeLabel);
  26. _szVolumeTitle = NewString(VolumeTitle);
  27. _szPrefixMap = NewString(PrefixMap);
  28. if (!(_szVolumeLabel && _szVolumeTitle && _szPrefixMap))
  29. {
  30. INET_ASSERT(FALSE);
  31. _Status = ERROR_NOT_ENOUGH_MEMORY;
  32. return;
  33. }
  34. _cbPrefixMap = strlen(PrefixMap);
  35. _cbMaxFileSize = MAX_FILE_SIZE_TO_MIGRATE;
  36. _Status = ERROR_SUCCESS;
  37. }
  38. /*-----------------------------------------------------------------------------
  39. CInstCon::~CInstCon
  40. -----------------------------------------------------------------------------*/
  41. CInstCon::~CInstCon()
  42. {
  43. delete _szPrefixMap;
  44. delete _szVolumeLabel;
  45. delete _szVolumeTitle;
  46. }
  47. /*------------------ URL_CONTAINER virtual overrides-------------------------*/
  48. /*-----------------------------------------------------------------------------
  49. CInstCon::GetPrefixMap
  50. -----------------------------------------------------------------------------*/
  51. LPSTR CInstCon::GetPrefixMap()
  52. {
  53. return _szPrefixMap;
  54. }
  55. /*-----------------------------------------------------------------------------
  56. CInstCon::GetVolumeLabel
  57. -----------------------------------------------------------------------------*/
  58. LPSTR CInstCon::GetVolumeLabel()
  59. {
  60. return _szVolumeLabel;
  61. }
  62. /*-----------------------------------------------------------------------------
  63. CInstCon::GetVolumeTitle
  64. -----------------------------------------------------------------------------*/
  65. LPSTR CInstCon::GetVolumeTitle()
  66. {
  67. return _szVolumeTitle;
  68. }
  69. /*-----------------------------------------------------------------------------
  70. CInstCon::AddUrl
  71. -----------------------------------------------------------------------------*/
  72. DWORD CInstCon::AddUrl (AddUrlArg* pArgs)
  73. {
  74. pArgs->dwEntryType |= INSTALLED_CACHE_ENTRY;
  75. return URL_CONTAINER::AddUrl(pArgs);
  76. }
  77. /*-----------------------------------------------------------------------------
  78. CInstCon::RetrieveUrl
  79. -----------------------------------------------------------------------------*/
  80. DWORD CInstCon::RetrieveUrl(LPCSTR UrlName, LPCACHE_ENTRY_INFO EntryInfo,
  81. LPDWORD EntryInfoSize, DWORD dwLookupFlags,
  82. DWORD dwRetrievalFlags)
  83. {
  84. DWORD dwError;
  85. BOOL fMustUnlock;
  86. INET_ASSERT(EntryInfo && EntryInfoSize);
  87. if (!LockContainer(&fMustUnlock))
  88. {
  89. dwError = GetLastError();
  90. goto exit;
  91. }
  92. dwError = GetEntry(UrlName, EntryInfo, EntryInfoSize, dwLookupFlags);
  93. exit:
  94. if (fMustUnlock) UnlockContainer();
  95. return dwError;
  96. }
  97. /*-----------------------------------------------------------------------------
  98. CInstCon::GetUrlInfo
  99. -----------------------------------------------------------------------------*/
  100. DWORD CInstCon::GetUrlInfo(LPCSTR szUrlName, LPCACHE_ENTRY_INFO pei,
  101. LPDWORD pcbei, DWORD dwLookupFlags, DWORD dwEntryFlags)
  102. {
  103. DWORD dwError;
  104. DWORD cbeiTemp = 0x256;
  105. BYTE bTemp[0x256];
  106. BOOL fMustUnlock;
  107. if (!LockContainer(&fMustUnlock))
  108. {
  109. dwError = GetLastError();
  110. goto exit;
  111. }
  112. // Zero buffer case.
  113. if (pei && pcbei)
  114. {
  115. dwError = GetEntry(szUrlName, pei, pcbei, dwLookupFlags);
  116. goto exit;
  117. }
  118. // Zero buffer case.
  119. if (dwEntryFlags & INTERNET_CACHE_FLAG_ENTRY_OR_MAPPING)
  120. {
  121. // Return success to indicate that a mapping exists.
  122. // We wouldn't have gotten here otherwise.
  123. dwError = ERROR_SUCCESS;
  124. }
  125. else
  126. {
  127. // Otherwise, no flag passed in. Only return
  128. // success if the entry has been successfully found.
  129. dwError = GetEntry(szUrlName, (LPCACHE_ENTRY_INFO) bTemp,
  130. &cbeiTemp, dwLookupFlags);
  131. }
  132. exit:
  133. if (fMustUnlock) UnlockContainer();
  134. return dwError;
  135. }
  136. /*--------------------- CInstCon Private Functions-----------------------------*/
  137. /*-----------------------------------------------------------------------------
  138. CInstCon::GetEntry
  139. -----------------------------------------------------------------------------*/
  140. DWORD CInstCon::GetEntry(LPCSTR UrlName, LPCACHE_ENTRY_INFO EntryInfo,
  141. LPDWORD EntryInfoSize, DWORD dwLookupFlags)
  142. {
  143. INT cbOld, cbNew, cbDiff;
  144. DWORD cbOriginalInfoSize = *EntryInfoSize;
  145. DWORD dwError = ERROR_SUCCESS, dwCDStatus;
  146. DWORD cb;
  147. LPSTR ptr;
  148. // Try to get it from the CD.
  149. dwCDStatus = GetEntryFromCD(UrlName, EntryInfo, EntryInfoSize);
  150. switch(dwCDStatus)
  151. {
  152. // Couldn't find it on the CD.
  153. case ERROR_FILE_NOT_FOUND:
  154. case ERROR_PATH_NOT_FOUND:
  155. // Not on CD. Look in memory mapped file.
  156. dwError = URL_CONTAINER::RetrieveUrl(UrlName, (EntryInfo ? &EntryInfo : NULL),
  157. EntryInfoSize, dwLookupFlags,
  158. RETRIEVE_WITH_CHECKS);
  159. break;
  160. // CD not in drive.
  161. case ERROR_INVALID_DRIVE:
  162. case ERROR_NOT_READY:
  163. case ERROR_WRONG_DISK:
  164. dwError = ERROR_INTERNET_INSERT_CDROM;
  165. break;
  166. // Found it on the CD.
  167. case ERROR_SUCCESS:
  168. dwError = ERROR_SUCCESS;
  169. break;
  170. default:
  171. // Some other error.
  172. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  173. }
  174. return dwError;
  175. }
  176. /*-----------------------------------------------------------------------------
  177. CInstCon::MapUrlToAbsPath
  178. -----------------------------------------------------------------------------*/
  179. VOID CInstCon::MapUrlToAbsPath(LPSTR UrlName,
  180. LPSTR szAbsPath, LPDWORD pcbAbsPath)
  181. {
  182. // Construct the absolute path to the file.
  183. memcpy(szAbsPath, _szPrefixMap, _cbPrefixMap + 1);
  184. LPSTR ptr = UrlName + _CachePrefixLen;
  185. DWORD cbSuffix = strlen(ptr);
  186. *pcbAbsPath = _cbPrefixMap + cbSuffix;
  187. memcpy(szAbsPath + _cbPrefixMap, ptr, cbSuffix + 1);
  188. // Convert all forward slashes to back slashes,
  189. // including any that were inadvertently placed
  190. // in the prefix map. This path might be returned
  191. // to the caller.
  192. ptr = szAbsPath;
  193. while (*ptr++)
  194. {
  195. #ifndef unix
  196. if (*ptr == '/')
  197. *ptr = '\\';
  198. #else
  199. if (*ptr == '\\')
  200. *ptr = '/';
  201. #endif /* unix */
  202. }
  203. // Unescape - final length may be less than
  204. // pcbAbsPath, but is always null terminated.
  205. UrlUnescapeInPlace(szAbsPath, NULL);
  206. }
  207. /*-----------------------------------------------------------------------------
  208. CInstCon::GetEntryFromCD
  209. -----------------------------------------------------------------------------*/
  210. DWORD CInstCon::GetEntryFromCD(LPCSTR UrlName,
  211. LPCACHE_ENTRY_INFO EntryInfo,
  212. LPDWORD EntryInfoSize)
  213. {
  214. LPBYTE pb;
  215. CHAR szAbsPath[MAX_PATH], *ptr;
  216. DWORD cbUrl, cbSuffix, cbAbsPath, cbSizeRequired, cbExt, i,
  217. dwError = ERROR_SUCCESS;
  218. LONGLONG llZero = (LONGLONG) 0;
  219. WIN32_FILE_ATTRIBUTE_DATA FileAttributes;
  220. CHAR szVolumeLabel[MAX_PATH];
  221. CHAR szVolRoot[4];
  222. memcpy(szVolRoot, _szPrefixMap, 2);
  223. memcpy(szVolRoot + 2, DIR_SEPARATOR_STRING, sizeof(DIR_SEPARATOR_STRING));
  224. // First check that the correct CD is inserted.
  225. if (GetVolumeInformation(szVolRoot, szVolumeLabel, MAX_PATH,
  226. NULL, NULL, NULL, NULL, 0))
  227. {
  228. if (strcmp(_szVolumeLabel, szVolumeLabel))
  229. {
  230. dwError = ERROR_WRONG_DISK;
  231. goto exit;
  232. }
  233. }
  234. else
  235. {
  236. dwError = ERROR_INVALID_DRIVE;
  237. goto exit;
  238. }
  239. // ---- Find the file and file info from the url -----
  240. cbUrl = strlen(UrlName);
  241. // Formulate path to file.
  242. MapUrlToAbsPath((LPSTR) UrlName, szAbsPath, &cbAbsPath);
  243. // Determine required CACHE_ENTRY_INFO buffer size.
  244. cbSizeRequired = sizeof(CACHE_ENTRY_INFO)
  245. + cbUrl + 1 + cbAbsPath + 1 + MAX_EXTENSION_LEN + 1 + sizeof(HTTP_OK);
  246. if (cbSizeRequired > *EntryInfoSize)
  247. {
  248. dwError = ERROR_INSUFFICIENT_BUFFER;
  249. goto exit;
  250. }
  251. // Get the file information. Shouldn't be a directory.
  252. dwError = GetFileSizeAndTimeByName(szAbsPath, &FileAttributes);
  253. if (dwError != ERROR_SUCCESS)
  254. {
  255. if (FileAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  256. {
  257. dwError = ERROR_FILE_NOT_FOUND;
  258. }
  259. goto exit;
  260. }
  261. // ---- Assemble the CACHE_ENTRY_INFO structure to return ----
  262. // Urlname.
  263. pb = (LPBYTE) EntryInfo + sizeof(CACHE_ENTRY_INFO);
  264. memcpy(pb, UrlName, cbUrl + 1);
  265. EntryInfo->lpszSourceUrlName = (LPSTR) pb;
  266. // Filename.
  267. pb += cbUrl + 1;
  268. strcpy((LPSTR) pb, szAbsPath);
  269. EntryInfo->lpszLocalFileName = (LPSTR) pb;
  270. // Header.
  271. pb += cbAbsPath + 1;
  272. memcpy(pb, HTTP_OK, sizeof(HTTP_OK));
  273. EntryInfo->lpHeaderInfo = (LPSTR)pb;
  274. // File extension
  275. cbExt = 0;
  276. ptr = (LPSTR) UrlName + cbUrl;
  277. for (i = 0; i < MAX_EXTENSION_LEN+1; i++)
  278. {
  279. if (*(--ptr) == '.')
  280. {
  281. cbExt = i+1;
  282. break;
  283. }
  284. }
  285. if (cbExt)
  286. {
  287. pb += sizeof(HTTP_OK);
  288. memcpy(pb, ptr+1, cbExt + 1);
  289. EntryInfo->lpszFileExtension = (LPSTR) pb;
  290. }
  291. else
  292. EntryInfo->lpszFileExtension = NULL;
  293. pb += cbExt +1;
  294. INET_ASSERT((DWORD) ((LPCACHE_ENTRY_INFO) pb - EntryInfo) < cbSizeRequired);
  295. // Version , type, count, hit rate, file size.
  296. EntryInfo->dwStructSize = URL_CACHE_VERSION_NUM;
  297. EntryInfo->CacheEntryType = INSTALLED_CACHE_ENTRY;
  298. EntryInfo->dwUseCount = 0;
  299. EntryInfo->dwHitRate = 0;
  300. EntryInfo->dwSizeHigh = FileAttributes.nFileSizeHigh;
  301. EntryInfo->dwSizeLow = FileAttributes.nFileSizeLow;
  302. // Times: modified, expired, accessed, synced.
  303. EntryInfo->LastModifiedTime = FileAttributes.ftCreationTime;
  304. EntryInfo->ExpireTime = *(FILETIME*) &llZero;
  305. // BUGBUG - getcurrent time for both.
  306. EntryInfo->LastAccessTime = FileAttributes.ftLastAccessTime;
  307. EntryInfo->LastSyncTime = *(FILETIME*) &llZero;
  308. // Header size, file extension, exempt delta.
  309. EntryInfo->dwHeaderInfoSize = sizeof(HTTP_OK);
  310. EntryInfo->dwExemptDelta = 0;
  311. // Buffer consumed.
  312. *EntryInfoSize = cbSizeRequired - sizeof(CACHE_ENTRY_INFO);
  313. exit:
  314. return dwError;
  315. }
  316. /*-----------------------------------------------------------------------------
  317. CInstCon::AddEntryToIndex
  318. -----------------------------------------------------------------------------*/
  319. DWORD CInstCon::AddEntryToIndex(LPCACHE_ENTRY_INFO EntryInfo,
  320. LPDWORD EntryInfoSize)
  321. {
  322. DWORD dwError;
  323. AddUrlArg args;
  324. CHAR szFileName[MAX_PATH];
  325. // Create a local file name for the hard disk.
  326. *szFileName = '\0';
  327. dwError = URL_CONTAINER::CreateUniqueFile(EntryInfo->lpszSourceUrlName,
  328. NULL, EntryInfo->lpszFileExtension, szFileName, NULL);
  329. if (dwError != ERROR_SUCCESS)
  330. goto exit;
  331. // Copy the file from the CD.
  332. // CreateUniqueFile has already created a file of 0 bytes.
  333. if (!CopyFile(EntryInfo->lpszLocalFileName, szFileName, FALSE))
  334. {
  335. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  336. goto exit;
  337. }
  338. // Add the entry to the index.
  339. // Url, filename, file size and extension.
  340. memset(&args, 0, sizeof(args));
  341. args.pszUrl = EntryInfo->lpszSourceUrlName;
  342. args.pszFilePath = szFileName;
  343. args.dwFileSize = EntryInfo->dwSizeLow;
  344. args.pszFileExt = EntryInfo->lpszFileExtension;
  345. args.dwEntryType = EntryInfo->CacheEntryType;
  346. // Headers.
  347. args.pbHeaders = EntryInfo->lpHeaderInfo;
  348. args.cbHeaders = EntryInfo->dwHeaderInfoSize;
  349. // Times: last modified and expired.
  350. args.qwLastMod = FT2LL(EntryInfo->LastModifiedTime);
  351. args.qwExpires = FT2LL(EntryInfo->ExpireTime);
  352. // Redirect.
  353. args.pszRedirect = NULL;
  354. args.fImage = FALSE;
  355. // Add the url to the index.
  356. dwError = AddUrl(&args);
  357. if (dwError != ERROR_SUCCESS)
  358. goto exit;
  359. // Retrieve the entry from the index. We do this because the EntryInfo
  360. // structure returned from the CD references the CD filename.
  361. // PERFPERF - we could optimize this by fixing up the EntryInfo
  362. // structure to reference the CD filename.
  363. dwError = URL_CONTAINER::RetrieveUrl(EntryInfo->lpszSourceUrlName,
  364. (EntryInfo ? &EntryInfo : NULL), EntryInfoSize, NULL, RETRIEVE_WITH_CHECKS);
  365. exit:
  366. return dwError;
  367. }