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.

638 lines
17 KiB

  1. /*****************************************************************************
  2. * *
  3. * FILEOFF.C *
  4. * *
  5. * Copyright (C) Microsoft Corporation 1995. *
  6. * All Rights reserved. *
  7. * *
  8. ******************************************************************************
  9. * *
  10. * Module Intent *
  11. * *
  12. * File Offset data type to replace using LONG for file offsets to handle *
  13. * files larger than 4 gigs in size. *
  14. * WARNING: To support 68K retail version, some functions don't have the
  15. * Pascal keyword. MSVC 4.0 had a bug that caused structure parameter to *
  16. * destroyed *
  17. * *
  18. ******************************************************************************
  19. * *
  20. * Current Owner: davej *
  21. *****************************************************************************/
  22. /*****************************************************************************
  23. *
  24. * Created 07/28/95 - davej
  25. * 3/05/97 erinfox Change errors to HRESULTS
  26. *
  27. *****************************************************************************/
  28. static char s_aszModule[] = __FILE__; /* For error report */
  29. #include <mvopsys.h>
  30. #include <orkin.h>
  31. #include <fileoff.h>
  32. /*****************************************************************************
  33. * *
  34. * Globals *
  35. * *
  36. *****************************************************************************/
  37. FILEOFFSET EXPORT_API foNil = {0L, 0L};
  38. FILEOFFSET EXPORT_API foMax = {0xffffffffL,0x7ffffffeL};
  39. FILEOFFSET EXPORT_API foMin = {0x00000000L,0x80000001L};
  40. FILEOFFSET EXPORT_API foInvalid = {0xffffffffL, 0xffffffffL};
  41. /*****************************************************************************
  42. * *
  43. * Defines *
  44. * *
  45. *****************************************************************************/
  46. /*****************************************************************************
  47. * *
  48. * Prototypes *
  49. * *
  50. *****************************************************************************/
  51. /***************************************************************************
  52. * *
  53. * Private Functions *
  54. * *
  55. ***************************************************************************/
  56. /***************************************************************************
  57. *
  58. * @doc INTERNAL
  59. *
  60. * @func FILEOFFSET PASCAL FAR | MakeFo |
  61. * Make a file offset from two dwords
  62. *
  63. * @parm DWORD | dwLo |
  64. * Low order dword
  65. *
  66. * @parm DWORD | dwHi |
  67. * High order dword
  68. *
  69. * @rdesc Returns a double DWORD file offset struct
  70. *
  71. * @comm
  72. * Use this function to build file offsets that can be passed to other
  73. * functions that need them as input.
  74. *
  75. ***************************************************************************/
  76. FILEOFFSET PASCAL FAR EXPORT_API MakeFo(DWORD dwLo, DWORD dwHi)
  77. {
  78. FILEOFFSET fo;
  79. fo.dwOffset=dwLo;
  80. fo.dwHigh=dwHi;
  81. return fo;
  82. }
  83. /***************************************************************************
  84. *
  85. * @doc PRIVATE
  86. *
  87. * @func FILEOFFSET PASCAL FAR | FoFromSz |
  88. * Convert a variable byte value to a FILEOFFSET
  89. *
  90. * @parm LPBYTE | szBytes |
  91. * Byte array containing variable byte length
  92. *
  93. * @rdesc Returns a double DWORD file offset struct from data of the form:
  94. * If High Bit Set, more bits follow (up to 9 bytes for 64 bits).
  95. * max for: 1 byte = 127
  96. * 2 bytes = 16384
  97. * 3 bytes = 2 M
  98. * 4 bytes = 268 M
  99. * 5 bytes = 34 G
  100. * 6 bytes = 4 T
  101. * 7 bytes = 562 T
  102. * 8 bytes = 72 Q
  103. * 9 bytes = 9223 Q (virtually infinite)
  104. *
  105. * @comm
  106. * Only a maximum of 9 bytes will be read from szBytes in the worst
  107. * case (or likely if szBytes points to invalid data). Use <f LenSzFo>
  108. * to get the length of a byte array for advancing to the next encoded
  109. * offset for example.
  110. *
  111. ***************************************************************************/
  112. FILEOFFSET PASCAL FAR EXPORT_API FoFromSz(LPBYTE sz)
  113. {
  114. register DWORD offset;
  115. register FILEOFFSET fo;
  116. register DWORD high=0L;
  117. for (;;)
  118. {
  119. offset=*sz; // Insert Segment A
  120. if (!(*(sz++)&0x80))
  121. break;
  122. offset&=0x7f;
  123. offset|=((DWORD)(*sz))<<7; // Insert Segment B
  124. if (!(*(sz++)&0x80))
  125. break;
  126. offset&=0x3fff;
  127. offset|=((DWORD)(*sz))<<14; // Insert Segment C
  128. if (!(*(sz++)&0x80))
  129. break;
  130. offset&=0x1fffff;
  131. offset|=(((DWORD)*sz))<<21; // Insert Segment D
  132. if (!(*(sz++)&0x80))
  133. break;
  134. offset&=0xfffffff;
  135. offset|=((DWORD)(*sz))<<28; // Insert Segment E
  136. high|=(*sz)>>4;
  137. if (!(*(sz++)&0x80))
  138. break;
  139. high&=0x7;
  140. high|=(((DWORD)*sz))<<3; // Insert Segment F;
  141. if (!(*(sz++)&0x80))
  142. break;
  143. high&=0x3ff;
  144. high|=((DWORD)(*sz))<<10; // Insert Segment G
  145. if (!(*(sz++)&0x80))
  146. break;
  147. high&=0x1ffff;
  148. high|=((DWORD)(*sz))<<17; // Insert Segment H
  149. if (!(*(sz++)&0x80))
  150. break;
  151. high&=0xffffff;
  152. high|=((DWORD)(*sz))<<24; // Segment I
  153. break;
  154. }
  155. fo.dwOffset=offset;
  156. fo.dwHigh=high;
  157. return fo;
  158. }
  159. /***************************************************************************
  160. *
  161. * @doc PRIVATE
  162. *
  163. * @func WORD PASCAL FAR | FoToSz |
  164. * Convert a file offset to a string
  165. *
  166. * @parm FILEOFFSET | fo |
  167. * File offset to convert to string representation
  168. *
  169. * @parm LPBYTE | szBytes |
  170. * Byte array to contain variable byte address
  171. *
  172. * @rdesc Returns number of bytes copied.
  173. * See <f LcbFromSz> for description of byte array format
  174. *
  175. * @comm
  176. * The byte array should contain at least 9 valid bytes should be allocated,
  177. * since at most the 9 bytes starting at <p szBytes> may be filled in.
  178. *
  179. ***************************************************************************/
  180. WORD PASCAL FAR EXPORT_API FoToSz(FILEOFFSET fo, LPBYTE sz)
  181. {
  182. register DWORD offset = fo.dwOffset;
  183. register DWORD high = fo.dwHigh;
  184. WORD wSize=1;
  185. for (;;)
  186. {
  187. *sz=(BYTE)(offset&0x7f); // A byte
  188. offset>>=7;
  189. if (!(offset|high))
  190. break;
  191. wSize++;
  192. *(sz++)|=0x80;
  193. *sz=(BYTE)(offset&0x7f); // B byte
  194. offset>>=7;
  195. if (!(offset|high))
  196. break;
  197. wSize++;
  198. *(sz++)|=0x80;
  199. *sz=(BYTE)(offset&0x7f); // C byte
  200. offset>>=7;
  201. if (!(offset|high))
  202. break;
  203. wSize++;
  204. *(sz++)|=0x80;
  205. *sz=(BYTE)(offset&0x7f); // D byte
  206. offset>>=7;
  207. if (!(offset|high))
  208. break;
  209. wSize++;
  210. *(sz++)|=0x80;
  211. *sz=(BYTE)(offset&0x0f); // E byte
  212. *sz|=(BYTE)((high&0x07)<<4);
  213. high>>=3;
  214. if (!high)
  215. break;
  216. wSize++;
  217. *(sz++)|=0x80;
  218. *sz=(BYTE)(high&0x7f); // F Byte
  219. high>>=7;
  220. if (!high)
  221. break;
  222. wSize++;
  223. *(sz++)|=0x80;
  224. *sz=(BYTE)(high&0x7f); // G Byte
  225. high>>=7;
  226. if (!high)
  227. break;
  228. wSize++;
  229. *(sz++)|=0x80;
  230. *sz=(BYTE)(high&0x7f); // H Byte
  231. high>>=7;
  232. if (!high)
  233. break;
  234. wSize++;
  235. *(sz++)|=0x80;
  236. *sz=(BYTE)high; // I byte
  237. break;
  238. }
  239. return wSize;
  240. }
  241. /***************************************************************************
  242. *
  243. * @doc PRIVATE
  244. *
  245. * @func WORD PASCAL FAR | LenSzFo |
  246. * Find number of bytes comprising this byte-array address code
  247. *
  248. * @parm LPBYTE | szBytes |
  249. * Byte array containing variable byte address
  250. *
  251. * @rdesc Returns number of bytes in byte-array for this address
  252. *
  253. ***************************************************************************/
  254. WORD PASCAL FAR EXPORT_API LenSzFo(LPBYTE sz)
  255. {
  256. register WORD wLen=1;
  257. while ((*(sz++))&0x80)
  258. wLen++;
  259. return wLen;
  260. }
  261. /***************************************************************************
  262. *
  263. * @doc PRIVATE
  264. *
  265. * @func FILEOFFSET FAR | FoAddDw |
  266. * Add a dword to a file offset
  267. *
  268. * @parm FILEOFFSET | fo |
  269. * Byte array containing variable byte length
  270. *
  271. * @parm DWORD | dwAdd |
  272. * Add this amount to the file offset
  273. *
  274. * @rdesc Returns the sum of the file offset fo and dwAdd as a FILEOFFSET.
  275. * Since only a dword is added, the dwHigh dword will never increase
  276. * more than one.
  277. *
  278. *
  279. ***************************************************************************/
  280. FILEOFFSET FAR EXPORT_API FoAddDw(FILEOFFSET fo, DWORD dwAdd)
  281. {
  282. register FILEOFFSET foSum = fo;
  283. foSum.dwOffset+=dwAdd;
  284. if (foSum.dwOffset<fo.dwOffset)
  285. foSum.dwHigh++;
  286. return foSum;
  287. }
  288. /***************************************************************************
  289. *
  290. * @doc INTERNAL
  291. *
  292. * @func FILEOFFSET FAR | FoAddFo |
  293. * Add a file offset to another file offset
  294. *
  295. * @parm FILEOFFSET | fo1 |
  296. * File Offset 1
  297. *
  298. * @parm FILEOFFSET | fo2 |
  299. * File Offset 2
  300. *
  301. * @rdesc Returns the sum fo1 + fo2 as a FILEOFFSET.
  302. *
  303. *
  304. ***************************************************************************/
  305. FILEOFFSET FAR EXPORT_API FoAddFo(FILEOFFSET fo1, FILEOFFSET fo2)
  306. {
  307. FILEOFFSET foSum;
  308. foSum.dwOffset=fo1.dwOffset+fo2.dwOffset;
  309. foSum.dwHigh=fo2.dwHigh+fo1.dwHigh+((foSum.dwOffset<fo1.dwOffset)?1:0);
  310. return foSum;
  311. }
  312. /***************************************************************************
  313. *
  314. * @doc INTERNAL
  315. *
  316. * @func FILEOFFSET FAR | FoSubFo |
  317. * Subtract file offsets, return a file offset
  318. *
  319. * @parm FILEOFFSET | fo1 |
  320. * File Offset 1
  321. *
  322. * @parm FILEOFFSET | fo2 |
  323. * File Offset 2
  324. *
  325. * @rdesc Returns fo1 - fo2 as a FILEOFFSET.
  326. *
  327. * @comm A Negative result will have 0xffffffff for the the dwHigh
  328. * member, and the dwOffset should be interpreted as a signed
  329. * value.
  330. *
  331. ***************************************************************************/
  332. FILEOFFSET FAR EXPORT_API FoSubFo(FILEOFFSET fo1, FILEOFFSET fo2)
  333. {
  334. FILEOFFSET foSum;
  335. foSum.dwOffset=fo1.dwOffset-fo2.dwOffset;
  336. foSum.dwHigh=fo1.dwHigh-fo2.dwHigh-((fo1.dwOffset<fo2.dwOffset)?1:0);
  337. return foSum;
  338. }
  339. /***************************************************************************
  340. *
  341. * @doc INTERNAL
  342. *
  343. * @func FILEOFFSET FAR | FoMultFo |
  344. * Multiply two offset values
  345. *
  346. * @parm FILEOFFSET | fo1 |
  347. * File Offset 1
  348. *
  349. * @parm FILEOFFSET | fo2 |
  350. * File Offset 2
  351. *
  352. * @rdesc Returns fo1 * fo2 as a FILEOFFSET.
  353. *
  354. * @comm If both fo1 and fo2 are less than 0xffffffff, then the result
  355. * is guaranteed to fit in a FILEOFFSET, otherwise, the result may
  356. * not be correct if overflow occurs.
  357. *
  358. ***************************************************************************/
  359. FILEOFFSET FAR EXPORT_API FoMultFo(FILEOFFSET fo1, FILEOFFSET fo2)
  360. {
  361. DWORD dwTop0,dwTop1,dwTop2,dwTop3;
  362. DWORD dwBot0,dwBot1,dwBot2,dwBot3;
  363. DWORD dwRes0=0;
  364. DWORD dwRes1=0;
  365. DWORD dwRes2=0;
  366. DWORD dwRes3=0;
  367. DWORD dwTemp;
  368. FILEOFFSET foResult;
  369. // Get terms
  370. dwTop0=(DWORD)HIWORD(fo1.dwHigh);
  371. dwTop1=(DWORD)LOWORD(fo1.dwHigh);
  372. dwTop2=(DWORD)HIWORD(fo1.dwOffset);
  373. dwTop3=(DWORD)LOWORD(fo1.dwOffset);
  374. dwBot0=(DWORD)HIWORD(fo2.dwHigh);
  375. dwBot1=(DWORD)LOWORD(fo2.dwHigh);
  376. dwBot2=(DWORD)HIWORD(fo2.dwOffset);
  377. dwBot3=(DWORD)LOWORD(fo2.dwOffset);
  378. // Do term by term multiplication and accumulate column results
  379. dwTemp=dwTop3*dwBot3;
  380. dwRes3+=LOWORD(dwTemp);
  381. dwRes2+=HIWORD(dwTemp);
  382. dwTemp=dwTop2*dwBot3;
  383. dwRes2+=LOWORD(dwTemp);
  384. dwRes1+=HIWORD(dwTemp);
  385. dwTemp=dwTop1*dwBot3;
  386. dwRes1+=LOWORD(dwTemp);
  387. dwRes0+=HIWORD(dwTemp);
  388. dwTemp=dwTop0*dwBot3;
  389. dwRes0+=LOWORD(dwTemp);
  390. dwTemp=dwTop3*dwBot2;
  391. dwRes2+=LOWORD(dwTemp);
  392. dwRes1+=HIWORD(dwTemp);
  393. dwTemp=dwTop2*dwBot2;
  394. dwRes1+=LOWORD(dwTemp);
  395. dwRes0+=HIWORD(dwTemp);
  396. dwTemp=dwTop1*dwBot2;
  397. dwRes0+=LOWORD(dwTemp);
  398. dwTemp=dwTop3*dwBot1;
  399. dwRes1+=LOWORD(dwTemp);
  400. dwRes0+=HIWORD(dwTemp);
  401. dwTemp=dwTop2*dwBot1;
  402. dwRes0+=LOWORD(dwTemp);
  403. dwTemp=dwTop3*dwBot0;
  404. dwRes0+=LOWORD(dwTemp);
  405. // Do the carry
  406. dwRes2+=HIWORD(dwRes3);
  407. dwRes1+=HIWORD(dwRes2);
  408. dwRes0+=HIWORD(dwRes1);
  409. // Make the result
  410. foResult.dwOffset=MAKELONG((dwRes3&0xffff),(dwRes2&0xffff));
  411. foResult.dwHigh=MAKELONG((dwRes1&0xffff),(dwRes0&0xffff));
  412. return foResult;
  413. }
  414. /***************************************************************************
  415. *
  416. * @doc INTERNAL
  417. *
  418. * @func FILEOFFSET PASCAL FAR | FoMultFo |
  419. * Multiply two offset values
  420. *
  421. * @parm DWORD | dw1 |
  422. * Mutplicand
  423. *
  424. * @parm FILEOFFSET | dw2 |
  425. * Multplier
  426. *
  427. * @rdesc Returns dw1 * dw2 as a FILEOFFSET.
  428. *
  429. ***************************************************************************/
  430. FILEOFFSET PASCAL FAR EXPORT_API FoMultDw(DWORD dw1, DWORD dw2)
  431. {
  432. DWORD dwTop2,dwTop3;
  433. DWORD dwBot2,dwBot3;
  434. DWORD dwRes0=0;
  435. DWORD dwRes1=0;
  436. DWORD dwRes2=0;
  437. DWORD dwRes3=0;
  438. DWORD dwTemp;
  439. FILEOFFSET foResult;
  440. // Get terms
  441. dwTop2=(DWORD)HIWORD(dw1);
  442. dwTop3=(DWORD)LOWORD(dw1);
  443. dwBot2=(DWORD)HIWORD(dw2);
  444. dwBot3=(DWORD)LOWORD(dw2);
  445. // Do term by term multiplication and accumulate column results
  446. dwTemp=dwTop3*dwBot3;
  447. dwRes3+=LOWORD(dwTemp);
  448. dwRes2+=HIWORD(dwTemp);
  449. dwTemp=dwTop2*dwBot3;
  450. dwRes2+=LOWORD(dwTemp);
  451. dwRes1+=HIWORD(dwTemp);
  452. dwTemp=dwTop3*dwBot2;
  453. dwRes2+=LOWORD(dwTemp);
  454. dwRes1+=HIWORD(dwTemp);
  455. dwTemp=dwTop2*dwBot2;
  456. dwRes1+=LOWORD(dwTemp);
  457. dwRes0+=HIWORD(dwTemp);
  458. // Do the carry
  459. dwRes2+=HIWORD(dwRes3);
  460. dwRes1+=HIWORD(dwRes2);
  461. dwRes0+=HIWORD(dwRes1);
  462. // Make the result
  463. foResult.dwOffset=MAKELONG((dwRes3&0xffff),(dwRes2&0xffff));
  464. foResult.dwHigh=MAKELONG((dwRes1&0xffff),(dwRes0&0xffff));
  465. return foResult;
  466. }
  467. /***************************************************************************
  468. *
  469. * @doc INTERNAL
  470. *
  471. * @func DWORD PASCAL FAR | DwSubFo |
  472. * Return the difference of two file offsets
  473. *
  474. * @parm FILEOFFSET | foA |
  475. * File offset
  476. *
  477. * @parm FILEOFFSET | foB |
  478. * File offset to subtract from foA
  479. *
  480. * @rdesc Returns the difference foA - foB as a DWORD. Result undefined
  481. * for differences greater than the dword size of a long.
  482. *
  483. * @comm
  484. * If a negative value is expected, the returned dword may be interpreted
  485. * as a signed value.
  486. *
  487. ***************************************************************************/
  488. DWORD FAR EXPORT_API DwSubFo(FILEOFFSET foA, FILEOFFSET foB)
  489. {
  490. // When foA.dwHigh = foB.dwHigh+1, it still works.
  491. return foA.dwOffset-foB.dwOffset;
  492. }
  493. /***************************************************************************
  494. *
  495. * @doc INTERNAL
  496. *
  497. * @func FILEOFFSET PASCAL FAR | FoIsNil |
  498. * Check whether the file offset is Nil. Nil is defined to be {0L,0L}.
  499. *
  500. * @parm FILEOFFSET | fo |
  501. * File offset to check
  502. *
  503. * @rdesc Returns TRUE if the file offset is equivalent to Nil.
  504. *
  505. ***************************************************************************/
  506. BOOL PASCAL FAR EXPORT_API FoIsNil(FILEOFFSET fo)
  507. {
  508. return ((fo.dwOffset==foNil.dwOffset) && (fo.dwHigh==foNil.dwHigh))?TRUE:FALSE;
  509. }
  510. /***************************************************************************
  511. *
  512. * @doc INTERNAL
  513. *
  514. * @func FILEOFFSET PASCAL FAR | FoEquals |
  515. * Compare any two file offsets for equality
  516. *
  517. * @parm FILEOFFSET | fo1 |
  518. * File offset to check
  519. *
  520. * @parm FILEOFFSET | fo2 |
  521. * File offset to check against
  522. *
  523. * @rdesc Returns TRUE if fo1 == fo2
  524. *
  525. ***************************************************************************/
  526. BOOL PASCAL FAR EXPORT_API FoEquals(FILEOFFSET fo1, FILEOFFSET fo2)
  527. {
  528. return ((fo1.dwOffset==fo2.dwOffset) && (fo1.dwHigh==fo2.dwHigh))?TRUE:FALSE;
  529. }
  530. /***************************************************************************
  531. *
  532. * @doc INTERNAL
  533. *
  534. * @func FILEOFFSET PASCAL FAR | FoCompare |
  535. * Compare any two file offsets
  536. *
  537. * @parm FILEOFFSET | fo1 |
  538. * File offset to check
  539. *
  540. * @parm FILEOFFSET | fo2 |
  541. * File offset to check against
  542. *
  543. * @rdesc Returns negative if fo1 <lt> fo2, 0 if fo1 == fo2, positive if
  544. * fo1 > fo2
  545. *
  546. ***************************************************************************/
  547. short int PASCAL FAR EXPORT_API FoCompare(FILEOFFSET foLeft, FILEOFFSET foRight)
  548. {
  549. if (foLeft.dwHigh==foRight.dwHigh)
  550. {
  551. if (foLeft.dwOffset<foRight.dwOffset)
  552. return -1;
  553. else if (foLeft.dwOffset>foRight.dwOffset)
  554. return 1;
  555. else
  556. return 0;
  557. }
  558. else if ((long)foLeft.dwHigh<(long)foRight.dwHigh)
  559. return -1;
  560. else
  561. return 1;
  562. }