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.

641 lines
19 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: enum.cpp
  6. * Content Handles all of the file caching of device caps.
  7. *
  8. *
  9. ***************************************************************************/
  10. #include "ddrawpr.h"
  11. #include <stdio.h>
  12. #include "d3dobj.hpp"
  13. #include "enum.hpp"
  14. #include "d3di.hpp"
  15. #include "shlobj.h"
  16. #define DXCACHEFILENAME "\\d3d8caps.dat"
  17. #define DXTEMPFILENAME "\\d3d8caps.tmp"
  18. typedef struct _FDEVICEHEADER
  19. {
  20. DWORD VendorId;
  21. DWORD DeviceId;
  22. DWORD SubSysId;
  23. DWORD Revision;
  24. DWORD FileOffset;
  25. DWORD Size;
  26. } FDEVICEHEADER;
  27. HANDLE OpenCacheFile(DWORD dwDesiredAccess, DWORD dwCreationDisposition, char * pName, char * pPath)
  28. {
  29. char FName[MAX_PATH + 16];
  30. GetSystemDirectory(FName, MAX_PATH);
  31. lstrcat(FName, pName);
  32. HANDLE h = CreateFile( FName,
  33. dwDesiredAccess,
  34. FILE_SHARE_READ,
  35. NULL,
  36. dwCreationDisposition,
  37. FILE_ATTRIBUTE_NORMAL,
  38. NULL);
  39. #ifdef WINNT
  40. if (INVALID_HANDLE_VALUE == h)
  41. {
  42. HMODULE hShlwapi=0;
  43. typedef HRESULT (WINAPI * PSHGETSPECIALFOLDERPATH) (HWND, LPTSTR, int, BOOL);
  44. PSHGETSPECIALFOLDERPATH pSHGetSpecialFolderPath=0;
  45. hShlwapi = LoadLibrary("SHELL32.DLL");
  46. if (hShlwapi)
  47. {
  48. pSHGetSpecialFolderPath = (PSHGETSPECIALFOLDERPATH) GetProcAddress(hShlwapi,"SHGetSpecialFolderPathA");
  49. if(pSHGetSpecialFolderPath)
  50. {
  51. HRESULT hr = pSHGetSpecialFolderPath(
  52. NULL,
  53. FName,
  54. CSIDL_LOCAL_APPDATA, // <user name>\Local Settings\Applicaiton Data (non roaming)
  55. TRUE);
  56. if (SUCCEEDED(hr))
  57. {
  58. lstrcat(FName, pName);
  59. h = CreateFile( FName,
  60. dwDesiredAccess,
  61. FILE_SHARE_READ,
  62. NULL,
  63. dwCreationDisposition,
  64. FILE_ATTRIBUTE_NORMAL,
  65. NULL);
  66. }
  67. }
  68. FreeLibrary(hShlwapi);
  69. }
  70. }
  71. #endif
  72. if (pPath)
  73. {
  74. lstrcpy(pPath, FName);
  75. }
  76. return h;
  77. }
  78. void ReadFromCache(D3DADAPTER_IDENTIFIER8* pDI,
  79. UINT* pCapsSize,
  80. BYTE** ppCaps)
  81. {
  82. HANDLE h;
  83. DWORD HeaderSize;
  84. DWORD NumRead;
  85. FDEVICEHEADER* pHeaderInfo = NULL;
  86. DWORD i;
  87. // Get the data for the device that we're looking for
  88. *pCapsSize = 0;
  89. *ppCaps = NULL;
  90. // Open the file and look for the device entry
  91. h = OpenCacheFile (GENERIC_READ, OPEN_EXISTING, DXCACHEFILENAME, NULL);
  92. if (h == INVALID_HANDLE_VALUE)
  93. {
  94. return;
  95. }
  96. ReadFile( h, &HeaderSize, sizeof(DWORD), &NumRead, NULL);
  97. if (NumRead < sizeof(DWORD))
  98. {
  99. goto FileError;
  100. }
  101. pHeaderInfo = (FDEVICEHEADER*) MemAlloc(HeaderSize);
  102. if (pHeaderInfo == NULL)
  103. {
  104. goto FileError;
  105. }
  106. ReadFile( h, pHeaderInfo, HeaderSize, &NumRead, NULL);
  107. if (NumRead < HeaderSize)
  108. {
  109. goto FileError;
  110. }
  111. for (i = 0; i < HeaderSize / sizeof(FDEVICEHEADER); i++)
  112. {
  113. if ((pHeaderInfo[i].VendorId == pDI->VendorId) &&
  114. (pHeaderInfo[i].DeviceId == pDI->DeviceId) &&
  115. (pHeaderInfo[i].SubSysId == pDI->SubSysId) &&
  116. (pHeaderInfo[i].Revision == pDI->Revision))
  117. {
  118. break;
  119. }
  120. }
  121. if (i < HeaderSize / sizeof(FDEVICEHEADER))
  122. {
  123. // We have info for the device - now we read it
  124. if (SetFilePointer (h, pHeaderInfo[i].FileOffset, NULL, FILE_BEGIN) !=
  125. pHeaderInfo[i].FileOffset)
  126. {
  127. goto FileError;
  128. }
  129. *ppCaps = (BYTE*) MemAlloc(pHeaderInfo[i].Size);
  130. if (*ppCaps == NULL)
  131. {
  132. goto FileError;
  133. }
  134. ReadFile( h, *ppCaps, pHeaderInfo[i].Size, &NumRead, NULL);
  135. if (NumRead < pHeaderInfo[i].Size)
  136. {
  137. MemFree(*ppCaps);
  138. *ppCaps = NULL;
  139. goto FileError;
  140. }
  141. // If we got this far, then everything worked
  142. *pCapsSize = pHeaderInfo[i].Size;
  143. }
  144. FileError:
  145. if (pHeaderInfo != NULL)
  146. {
  147. MemFree(pHeaderInfo);
  148. }
  149. CloseHandle(h);
  150. }
  151. void WriteToCache(D3DADAPTER_IDENTIFIER8* pDI,
  152. UINT CapsSize,
  153. BYTE* pCaps)
  154. {
  155. char FName[MAX_PATH + 16];
  156. char NewFName[MAX_PATH + 16];
  157. BOOL bNewFile = FALSE;
  158. HANDLE hOld;
  159. HANDLE hNew;
  160. DWORD NewHeaderSize;
  161. DWORD OldHeaderSize;
  162. DWORD NumWritten;
  163. DWORD NumRead;
  164. FDEVICEHEADER* pOldHeaderInfo = NULL;
  165. FDEVICEHEADER* pNewHeaderInfo = NULL;
  166. DWORD dwOffset;
  167. DWORD i;
  168. DWORD NewEntries;
  169. DWORD NextEntry;
  170. DWORD Biggest;
  171. BYTE* pBuffer = NULL;
  172. // Does the file already exist, or do we need to create a new one?
  173. hOld = OpenCacheFile (GENERIC_READ, OPEN_EXISTING, DXCACHEFILENAME, FName);
  174. if (hOld == INVALID_HANDLE_VALUE)
  175. {
  176. bNewFile = TRUE;
  177. }
  178. else
  179. {
  180. // We don't want this file to get over 65K. If writing this entry
  181. // will cause the file size to exceed that, then we will delete all
  182. // of the existing data and start from scratch.
  183. DWORD dwLow;
  184. DWORD dwHigh;
  185. dwLow = GetFileSize (hOld, &dwHigh);
  186. if ((dwHigh != 0) || ((sizeof(DWORD) - dwLow) < CapsSize))
  187. {
  188. CloseHandle(hOld);
  189. bNewFile = TRUE;
  190. }
  191. }
  192. if (bNewFile)
  193. {
  194. // We are creating a new file, which is pretty easy
  195. hNew = OpenCacheFile (GENERIC_WRITE, CREATE_ALWAYS, DXCACHEFILENAME, NewFName);
  196. if (hNew != INVALID_HANDLE_VALUE)
  197. {
  198. NewHeaderSize = sizeof (FDEVICEHEADER);
  199. WriteFile (hNew, &NewHeaderSize, sizeof(NewHeaderSize), &NumWritten, NULL);
  200. if (NumWritten == sizeof(NewHeaderSize))
  201. {
  202. FDEVICEHEADER DevHeader;
  203. DevHeader.VendorId = pDI->VendorId;
  204. DevHeader.DeviceId = pDI->DeviceId;
  205. DevHeader.SubSysId = pDI->SubSysId;
  206. DevHeader.Revision = pDI->Revision;
  207. DevHeader.FileOffset = sizeof(FDEVICEHEADER) + sizeof(DWORD);
  208. DevHeader.Size = CapsSize;
  209. WriteFile (hNew, &DevHeader, sizeof(DevHeader), &NumWritten, NULL);
  210. if (NumWritten == sizeof(DevHeader))
  211. {
  212. WriteFile (hNew, pCaps, CapsSize, &NumWritten, NULL);
  213. }
  214. }
  215. CloseHandle(hNew);
  216. }
  217. }
  218. else
  219. {
  220. // The file already exists, so we will create a new file and copy all of the contents
  221. // from the existing file over.
  222. hNew = OpenCacheFile (GENERIC_WRITE, CREATE_ALWAYS, DXTEMPFILENAME, NewFName);
  223. if (hNew == INVALID_HANDLE_VALUE)
  224. {
  225. goto FileError;
  226. }
  227. ReadFile (hOld, &OldHeaderSize, sizeof(DWORD), &NumRead, NULL);
  228. if (NumRead < sizeof(DWORD))
  229. {
  230. goto FileError;
  231. }
  232. pOldHeaderInfo = (FDEVICEHEADER*) MemAlloc(OldHeaderSize);
  233. if (pOldHeaderInfo == NULL)
  234. {
  235. goto FileError;
  236. }
  237. ReadFile (hOld, pOldHeaderInfo, OldHeaderSize, &NumRead, NULL);
  238. if (NumRead < OldHeaderSize)
  239. {
  240. goto FileError;
  241. }
  242. // How many entries will exist in the new header?
  243. NewEntries = 1;
  244. for (i = 0; i < OldHeaderSize / sizeof (FDEVICEHEADER); i++)
  245. {
  246. if ((pOldHeaderInfo[i].VendorId != pDI->VendorId) ||
  247. (pOldHeaderInfo[i].DeviceId != pDI->DeviceId) ||
  248. (pOldHeaderInfo[i].SubSysId != pDI->SubSysId) ||
  249. (pOldHeaderInfo[i].Revision != pDI->Revision))
  250. {
  251. NewEntries++;
  252. }
  253. }
  254. pNewHeaderInfo = (FDEVICEHEADER*) MemAlloc(sizeof(FDEVICEHEADER) * NewEntries);
  255. if (pNewHeaderInfo == NULL)
  256. {
  257. goto FileError;
  258. }
  259. // Fill in the header info for each device and save it to the new file
  260. dwOffset = (sizeof(FDEVICEHEADER) * NewEntries) + sizeof(DWORD);
  261. pNewHeaderInfo[0].VendorId = pDI->VendorId;
  262. pNewHeaderInfo[0].DeviceId = pDI->DeviceId;
  263. pNewHeaderInfo[0].SubSysId = pDI->SubSysId;
  264. pNewHeaderInfo[0].Revision = pDI->Revision;
  265. pNewHeaderInfo[0].FileOffset = dwOffset;
  266. pNewHeaderInfo[0].Size = CapsSize;
  267. dwOffset += CapsSize;
  268. NextEntry = 1;
  269. for (i = 0; i < OldHeaderSize / sizeof (FDEVICEHEADER); i++)
  270. {
  271. if ((pOldHeaderInfo[i].VendorId != pDI->VendorId) ||
  272. (pOldHeaderInfo[i].DeviceId != pDI->DeviceId) ||
  273. (pOldHeaderInfo[i].SubSysId != pDI->SubSysId) ||
  274. (pOldHeaderInfo[i].Revision != pDI->Revision))
  275. {
  276. pNewHeaderInfo[NextEntry].VendorId = pOldHeaderInfo[i].VendorId;
  277. pNewHeaderInfo[NextEntry].DeviceId = pOldHeaderInfo[i].DeviceId;
  278. pNewHeaderInfo[NextEntry].SubSysId = pOldHeaderInfo[i].SubSysId;
  279. pNewHeaderInfo[NextEntry].Revision = pOldHeaderInfo[i].Revision;
  280. pNewHeaderInfo[NextEntry].FileOffset = dwOffset;
  281. pNewHeaderInfo[NextEntry].Size = pOldHeaderInfo[i].Size;
  282. dwOffset += pOldHeaderInfo[i].Size;
  283. NextEntry++;
  284. }
  285. }
  286. NewHeaderSize = sizeof(FDEVICEHEADER) * NewEntries;
  287. WriteFile (hNew, &NewHeaderSize, sizeof(NewHeaderSize), &NumWritten, NULL);
  288. if (NumWritten != sizeof(NewHeaderSize))
  289. {
  290. goto FileError;
  291. }
  292. WriteFile (hNew, pNewHeaderInfo, NewHeaderSize, &NumWritten, NULL);
  293. if (NumWritten != NewHeaderSize)
  294. {
  295. goto FileError;
  296. }
  297. // Write the new device data to the file
  298. WriteFile (hNew, pCaps, CapsSize, &NumWritten, NULL);
  299. if (NumWritten != CapsSize)
  300. {
  301. goto FileError;
  302. }
  303. if (NewEntries > 1)
  304. {
  305. // Figure out how big the biggest device size is and allocate a buffer
  306. // to hold it
  307. Biggest = 0;
  308. for (i = 1; i < NewEntries; i++)
  309. {
  310. if (pNewHeaderInfo[i].Size > Biggest)
  311. {
  312. Biggest = pNewHeaderInfo[i].Size;
  313. }
  314. }
  315. pBuffer = (BYTE*) MemAlloc(Biggest);
  316. if (pBuffer == NULL)
  317. {
  318. goto FileError;
  319. }
  320. // Now read the device data from the old file and write it to
  321. // the new on.
  322. NextEntry = 0;
  323. for (i = 0; i < OldHeaderSize / sizeof (FDEVICEHEADER); i++)
  324. {
  325. if ((pOldHeaderInfo[i].VendorId != pDI->VendorId) ||
  326. (pOldHeaderInfo[i].DeviceId != pDI->DeviceId) ||
  327. (pOldHeaderInfo[i].SubSysId != pDI->SubSysId) ||
  328. (pOldHeaderInfo[i].Revision != pDI->Revision))
  329. {
  330. if (SetFilePointer (hOld, pOldHeaderInfo[i].FileOffset, NULL, FILE_BEGIN) !=
  331. pOldHeaderInfo[i].FileOffset)
  332. {
  333. goto FileError;
  334. }
  335. ReadFile (hOld, pBuffer, pOldHeaderInfo[i].Size, &NumRead, NULL);
  336. if (NumRead < pOldHeaderInfo[i].Size)
  337. {
  338. goto FileError;
  339. }
  340. WriteFile (hNew, pBuffer, pOldHeaderInfo[i].Size, &NumWritten, NULL);
  341. if (NumWritten != pOldHeaderInfo[i].Size)
  342. {
  343. goto FileError;
  344. }
  345. }
  346. }
  347. }
  348. // If we made it this far, then everything worked
  349. CloseHandle(hNew);
  350. CloseHandle(hOld);
  351. DeleteFile(FName);
  352. MoveFile(NewFName, FName);
  353. if (pNewHeaderInfo != NULL)
  354. {
  355. MemFree(pNewHeaderInfo);
  356. }
  357. if (pOldHeaderInfo != NULL)
  358. {
  359. MemFree(pOldHeaderInfo);
  360. }
  361. if (pBuffer != NULL)
  362. {
  363. MemFree(pBuffer);
  364. }
  365. return;
  366. FileError:
  367. CloseHandle(hNew);
  368. CloseHandle(hOld);
  369. DeleteFile(FName);
  370. DeleteFile(NewFName);
  371. if (pNewHeaderInfo != NULL)
  372. {
  373. MemFree(pNewHeaderInfo);
  374. }
  375. if (pOldHeaderInfo != NULL)
  376. {
  377. MemFree(pOldHeaderInfo);
  378. }
  379. if (pBuffer != NULL)
  380. {
  381. MemFree(pBuffer);
  382. }
  383. }
  384. }
  385. void RemoveFromCache(D3DADAPTER_IDENTIFIER8* pDI)
  386. {
  387. char FName[MAX_PATH + 16];
  388. char NewFName[MAX_PATH + 16];
  389. BOOL bNewFile = FALSE;
  390. HANDLE hOld;
  391. HANDLE hNew;
  392. DWORD NewHeaderSize;
  393. DWORD OldHeaderSize;
  394. DWORD NumWritten;
  395. DWORD NumRead;
  396. FDEVICEHEADER* pOldHeaderInfo = NULL;
  397. FDEVICEHEADER* pNewHeaderInfo = NULL;
  398. DWORD dwOffset;
  399. DWORD i;
  400. DWORD NewEntries;
  401. DWORD NextEntry;
  402. DWORD Biggest;
  403. BYTE* pBuffer = NULL;
  404. // Does the file already exist, or do we need to create a new one?
  405. hOld = OpenCacheFile (GENERIC_READ, OPEN_EXISTING, DXCACHEFILENAME, FName);
  406. if (hOld == INVALID_HANDLE_VALUE)
  407. {
  408. return;
  409. }
  410. ReadFile (hOld, &OldHeaderSize, sizeof(DWORD), &NumRead, NULL);
  411. if (NumRead < sizeof(DWORD))
  412. {
  413. goto FileError;
  414. }
  415. if (OldHeaderSize <= sizeof(FDEVICEHEADER))
  416. {
  417. // Theres only one entry in the file, so all we need to do
  418. // is delete it.
  419. DeleteFile(FName);
  420. return;
  421. }
  422. pOldHeaderInfo = (FDEVICEHEADER*) MemAlloc(OldHeaderSize);
  423. if (pOldHeaderInfo == NULL)
  424. {
  425. goto FileError;
  426. }
  427. ReadFile (hOld, pOldHeaderInfo, OldHeaderSize, &NumRead, NULL);
  428. if (NumRead < OldHeaderSize)
  429. {
  430. goto FileError;
  431. }
  432. // Create a new file and copy all of the contents from the existing file over.
  433. hNew = OpenCacheFile (GENERIC_WRITE, CREATE_ALWAYS, DXTEMPFILENAME, NewFName);
  434. if (hNew == INVALID_HANDLE_VALUE)
  435. {
  436. goto FileError;
  437. }
  438. // How many entries will exist in the new header?
  439. NewEntries = 0;
  440. for (i = 0; i < OldHeaderSize / sizeof (FDEVICEHEADER); i++)
  441. {
  442. if ((pOldHeaderInfo[i].VendorId != pDI->VendorId) ||
  443. (pOldHeaderInfo[i].DeviceId != pDI->DeviceId) ||
  444. (pOldHeaderInfo[i].SubSysId != pDI->SubSysId) ||
  445. (pOldHeaderInfo[i].Revision != pDI->Revision))
  446. {
  447. NewEntries++;
  448. }
  449. }
  450. pNewHeaderInfo = (FDEVICEHEADER*) MemAlloc(sizeof(FDEVICEHEADER) * NewEntries);
  451. if (pNewHeaderInfo == NULL)
  452. {
  453. goto FileError;
  454. }
  455. // Fill in the header info for each device and save it to the new file
  456. dwOffset = (sizeof(FDEVICEHEADER) * NewEntries) + sizeof(DWORD);
  457. NextEntry = 0;
  458. for (i = 0; i < OldHeaderSize / sizeof (FDEVICEHEADER); i++)
  459. {
  460. if ((pOldHeaderInfo[i].VendorId != pDI->VendorId) ||
  461. (pOldHeaderInfo[i].DeviceId != pDI->DeviceId) ||
  462. (pOldHeaderInfo[i].SubSysId != pDI->SubSysId) ||
  463. (pOldHeaderInfo[i].Revision != pDI->Revision))
  464. {
  465. pNewHeaderInfo[NextEntry].VendorId = pOldHeaderInfo[i].VendorId;
  466. pNewHeaderInfo[NextEntry].DeviceId = pOldHeaderInfo[i].DeviceId;
  467. pNewHeaderInfo[NextEntry].SubSysId = pOldHeaderInfo[i].SubSysId;
  468. pNewHeaderInfo[NextEntry].Revision = pOldHeaderInfo[i].Revision;
  469. pNewHeaderInfo[NextEntry].FileOffset = dwOffset;
  470. pNewHeaderInfo[NextEntry].Size = pOldHeaderInfo[i].Size;
  471. dwOffset += pOldHeaderInfo[i].Size;
  472. NextEntry++;
  473. }
  474. }
  475. NewHeaderSize = sizeof(FDEVICEHEADER) * NewEntries;
  476. WriteFile (hNew, &NewHeaderSize, sizeof(NewHeaderSize), &NumWritten, NULL);
  477. if (NumWritten != sizeof(NewHeaderSize))
  478. {
  479. goto FileError;
  480. }
  481. WriteFile (hNew, pNewHeaderInfo, NewHeaderSize, &NumWritten, NULL);
  482. if (NumWritten != NewHeaderSize)
  483. {
  484. goto FileError;
  485. }
  486. // Figure out how big the biggest device size is and allocate a buffer
  487. // to hold it
  488. Biggest = 0;
  489. for (i = 0; i < NewEntries; i++)
  490. {
  491. if (pNewHeaderInfo[i].Size > Biggest)
  492. {
  493. Biggest = pNewHeaderInfo[i].Size;
  494. }
  495. }
  496. pBuffer = (BYTE*) MemAlloc(Biggest);
  497. if (pBuffer == NULL)
  498. {
  499. goto FileError;
  500. }
  501. // Now read the device data from the old file and write it to
  502. // the new on.
  503. NextEntry = 0;
  504. for (i = 0; i < OldHeaderSize / sizeof (FDEVICEHEADER); i++)
  505. {
  506. if ((pOldHeaderInfo[i].VendorId != pDI->VendorId) ||
  507. (pOldHeaderInfo[i].DeviceId != pDI->DeviceId) ||
  508. (pOldHeaderInfo[i].SubSysId != pDI->SubSysId) ||
  509. (pOldHeaderInfo[i].Revision != pDI->Revision))
  510. {
  511. if (SetFilePointer (hOld, pOldHeaderInfo[i].FileOffset, NULL, FILE_BEGIN) !=
  512. pOldHeaderInfo[i].FileOffset)
  513. {
  514. goto FileError;
  515. }
  516. ReadFile (hOld, pBuffer, pOldHeaderInfo[i].Size, &NumRead, NULL);
  517. if (NumRead < pOldHeaderInfo[i].Size)
  518. {
  519. goto FileError;
  520. }
  521. WriteFile (hNew, pBuffer, pOldHeaderInfo[i].Size, &NumWritten, NULL);
  522. if (NumWritten != pOldHeaderInfo[i].Size)
  523. {
  524. goto FileError;
  525. }
  526. }
  527. }
  528. // If we made it this far, then everything worked
  529. CloseHandle(hNew);
  530. CloseHandle(hOld);
  531. DeleteFile(FName);
  532. MoveFile(NewFName, FName);
  533. if (pNewHeaderInfo != NULL)
  534. {
  535. MemFree(pNewHeaderInfo);
  536. }
  537. if (pOldHeaderInfo != NULL)
  538. {
  539. MemFree(pOldHeaderInfo);
  540. }
  541. if (pBuffer != NULL)
  542. {
  543. MemFree(pBuffer);
  544. }
  545. return;
  546. FileError:
  547. CloseHandle(hNew);
  548. CloseHandle(hOld);
  549. if (pNewHeaderInfo != NULL)
  550. {
  551. MemFree(pNewHeaderInfo);
  552. }
  553. if (pOldHeaderInfo != NULL)
  554. {
  555. MemFree(pOldHeaderInfo);
  556. }
  557. if (pBuffer != NULL)
  558. {
  559. MemFree(pBuffer);
  560. }
  561. }