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.

749 lines
18 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. csc_bmpu.c
  5. Abstract:
  6. This module implements the user mode utility functions of bitmaps
  7. associated with CSC files. CSC_BMP_U is an opaque structure. Must
  8. use the functions here to create/modify/destroy a CSC_BMP_U to
  9. ensure data integrity. The 'u' in the filename means "usermode."
  10. Author:
  11. Nigel Choi [t-nigelc] Sept 3, 1999
  12. --*/
  13. #include "pch.h"
  14. #ifdef CSC_ON_NT
  15. #pragma hdrstop
  16. #define UNICODE
  17. #endif //CSC_ON_NT
  18. #include "csc_bmpu.h"
  19. // append this to inode file name to get the stream name
  20. LPTSTR CscBmpAltStrmName = TEXT(STRMNAME);
  21. #ifdef DEBUG
  22. #define CSC_BitmapKdPrint(__bit,__x) {\
  23. if (((CSC_BITMAP_KDP_##__bit)==0) || (CSC_BitmapKdPrintVector & (CSC_BITMAP_KDP_##__bit))) {\
  24. DEBUG_PRINT(__x);\
  25. }\
  26. }
  27. #define CSC_BITMAP_KDP_ALWAYS 0x00000000
  28. #define CSC_BITMAP_KDP_REINT 0x00000001
  29. #define CSC_BITMAP_KDP_PRINTBITMAP 0x00000002
  30. // static ULONG CSC_BitmapKdPrintVector = 0XFFFFFFFF;
  31. static ULONG CSC_BitmapKdPrintVector = 0;
  32. #else
  33. #define CSC_BitmapKdPrint(__bit,__x) ;
  34. #endif
  35. /*++
  36. CSC_BitmapCreate()
  37. Routine Description:
  38. Allocates an appropriate in-memory bitmap CSC_BITMAP_U with size
  39. corresponding to filesize.
  40. Arguments:
  41. Returns:
  42. NULL if memory allocation error.
  43. pointer to the newly allocated bitmap if successful.
  44. Notes:
  45. --*/
  46. LPCSC_BITMAP_U
  47. CSC_BitmapCreate(
  48. DWORD filesize)
  49. {
  50. LPCSC_BITMAP_U bm;
  51. DWORD i;
  52. bm = (LPCSC_BITMAP_U)malloc(sizeof(CSC_BITMAP_U));
  53. if (bm == NULL)
  54. return NULL;
  55. bm->bitmapsize = filesize/BLOCKSIZE;
  56. if (filesize % BLOCKSIZE)
  57. bm->bitmapsize++;
  58. bm->numDWORD = bm->bitmapsize/(8*sizeof(DWORD));
  59. if (bm->bitmapsize % (8*sizeof(DWORD)))
  60. bm->numDWORD++;
  61. bm->reintProgress = 0; /* not reint yet */
  62. if (bm->bitmapsize) {
  63. bm->bitmap = (LPDWORD)malloc(bm->numDWORD*sizeof(DWORD));
  64. if (bm->bitmap == NULL) {
  65. free(bm);
  66. return NULL;
  67. }
  68. for (i = 0; i < bm->numDWORD; i++) {
  69. bm->bitmap[i] = 0;
  70. }
  71. } else {
  72. bm->bitmap = NULL;
  73. }
  74. return bm;
  75. }
  76. /*++
  77. CSC_BitmapDelete()
  78. Routine Description:
  79. Arguments:
  80. Returns:
  81. Notes:
  82. --*/
  83. void
  84. CSC_BitmapDelete(
  85. LPCSC_BITMAP_U *lplpbitmap)
  86. {
  87. if (lplpbitmap == NULL)
  88. return;
  89. if (*lplpbitmap == NULL)
  90. return;
  91. if ((*lplpbitmap)->bitmap)
  92. free((*lplpbitmap)->bitmap);
  93. free((*lplpbitmap));
  94. *lplpbitmap = NULL;
  95. }
  96. /*++
  97. CSC_BitmapIsMarked()
  98. Routine Description:
  99. Arguments:
  100. Returns:
  101. -1 if lpbitmap is NULL or bitoffset is larger than the bitmap
  102. TRUE if the bit is marked
  103. FALSE if the bit is unmarked
  104. Notes:
  105. --*/
  106. int
  107. CSC_BitmapIsMarked(
  108. LPCSC_BITMAP_U lpbitmap,
  109. DWORD bitoffset)
  110. {
  111. DWORD DWORDnum;
  112. DWORD bitpos;
  113. if (lpbitmap == NULL)
  114. return -1;
  115. if (bitoffset >= lpbitmap->bitmapsize)
  116. return -1;
  117. DWORDnum = bitoffset/(8*sizeof(DWORD));
  118. bitpos = 1 << bitoffset%(8*sizeof(DWORD));
  119. if (lpbitmap->bitmap[DWORDnum] & bitpos) {
  120. return TRUE;
  121. }
  122. return FALSE;
  123. }
  124. /*++
  125. CSC_BitmapGetBlockSize()
  126. Routine Description:
  127. Arguments:
  128. Returns:
  129. The pre-defined block size represented by one bit of the bitmap.
  130. Notes:
  131. --*/
  132. DWORD
  133. CSC_BitmapGetBlockSize()
  134. {
  135. return BLOCKSIZE;
  136. }
  137. /*++
  138. CSC_BitmapGetSize()
  139. Routine Description:
  140. Arguments:
  141. Returns:
  142. -1 if lpbitmap is NULL.
  143. The size of the bitmap passed in.
  144. Notes:
  145. --*/
  146. int
  147. CSC_BitmapGetSize(
  148. LPCSC_BITMAP_U lpbitmap)
  149. {
  150. if (lpbitmap == NULL)
  151. return -1;
  152. return lpbitmap->bitmapsize;
  153. }
  154. /*++
  155. CSC_BitmapStreamNameLen()
  156. Routine Description:
  157. returns the length of the CSC stream name including the colon, in bytes.
  158. Arguments:
  159. Returns:
  160. Notes:
  161. size is in bytes.
  162. --*/
  163. int
  164. CSC_BitmapStreamNameLen()
  165. {
  166. return lstrlen(CscBmpAltStrmName);
  167. }
  168. /*++
  169. CSC_BitmapAppendStreamName()
  170. Routine Description:
  171. Appends the CSC stream name to the existing path/file name fname.
  172. Arguments:
  173. fname is the sting buffer containing the path/file.
  174. bufsize is the buffer size.
  175. Returns:
  176. TRUE if append successful.
  177. FALSE if buffer is too small or other errors.
  178. Notes:
  179. Single-byte strings only.
  180. --*/
  181. int
  182. CSC_BitmapAppendStreamName(
  183. LPTSTR fname,
  184. DWORD bufsize)
  185. {
  186. int ret = TRUE;
  187. if ((lstrlen(fname) + lstrlen(CscBmpAltStrmName) + 1) > (int)bufsize) {
  188. return FALSE;
  189. }
  190. __try {
  191. ret = TRUE;
  192. lstrcat(fname, CscBmpAltStrmName);
  193. } __except(EXCEPTION_EXECUTE_HANDLER) {
  194. ret = FALSE;
  195. }
  196. return ret;
  197. }
  198. /*++
  199. CSC_BitmapRead()
  200. Routine Description:
  201. Reads the on-disk bitmap file, and if it exists, is not in use and valid,
  202. store it in *lplpbitmap. If *lplpbitmap is NULL allocate a new
  203. bitmap data structure. Otherwise, if *lplpbitmap is not NULL, the
  204. existing bitmap will be deleted and assigned the on-disk bitmap
  205. file.
  206. Arguments:
  207. filename is the file that contains the bitmap. If read from a
  208. stream, append the stream name before passing the filename in. The
  209. filename is used as is and no checking of validity of the name is
  210. performed. For default stream name, append the global LPSTR
  211. CscBmpAltStrmName.
  212. Returns:
  213. 1 if read successful
  214. 0 if lplpbitmap is NULL
  215. -1 if error in disk operation (open/read), memory allocating error,
  216. or invalid bitmap file format.
  217. -2 if bitmap not exist
  218. Notes:
  219. CODE.IMPROVEMENT design a better error message propagation mechanism.
  220. Bitmap open for exclusive access.
  221. --*/
  222. int
  223. CSC_BitmapRead(
  224. LPCSC_BITMAP_U *lplpbitmap,
  225. LPCTSTR filename)
  226. {
  227. CscBmpFileHdr hdr;
  228. HANDLE bitmapFile;
  229. DWORD bytesRead;
  230. DWORD bitmapByteSize;
  231. DWORD * bitmapBuf = NULL;
  232. DWORD errCode;
  233. int ret = 1;
  234. if (lplpbitmap == NULL)
  235. return 0;
  236. bitmapFile = CreateFile(
  237. filename,
  238. GENERIC_READ,
  239. 0, // No sharing; exclusive
  240. NULL,
  241. OPEN_EXISTING,
  242. FILE_ATTRIBUTE_NORMAL,
  243. NULL);
  244. if (bitmapFile == INVALID_HANDLE_VALUE) {
  245. errCode = GetLastError();
  246. if (errCode == ERROR_FILE_NOT_FOUND) {
  247. // File does not exist
  248. return -2;
  249. }
  250. return -1;
  251. }
  252. if (!ReadFile(
  253. bitmapFile,
  254. &hdr,
  255. sizeof(CscBmpFileHdr),
  256. &bytesRead, NULL)
  257. ) {
  258. ret = -1;
  259. goto CLOSEFILE;
  260. }
  261. if (
  262. bytesRead != sizeof(CscBmpFileHdr)
  263. ||
  264. hdr.magicnum != MAGICNUM
  265. ||
  266. !hdr.valid
  267. ||
  268. hdr.inuse
  269. ) {
  270. ret = -1;
  271. goto CLOSEFILE;
  272. }
  273. if (hdr.sizeinbits > 0) {
  274. bitmapByteSize = hdr.numDWORDs*sizeof(DWORD);
  275. bitmapBuf = (DWORD *)malloc(bitmapByteSize);
  276. if (!bitmapBuf) {
  277. ret = -1;
  278. goto CLOSEFILE;
  279. }
  280. if (!ReadFile(
  281. bitmapFile,
  282. bitmapBuf,
  283. bitmapByteSize,
  284. &bytesRead,
  285. NULL)
  286. ) {
  287. ret = -1;
  288. goto CLOSEFILE;
  289. }
  290. if (bytesRead != bitmapByteSize) {
  291. ret = -1;
  292. goto CLOSEFILE;
  293. }
  294. }
  295. if (*lplpbitmap) {
  296. // bitmap exist, dump old and create new
  297. if ((*lplpbitmap)->bitmap)
  298. free((*lplpbitmap)->bitmap);
  299. (*lplpbitmap)->bitmap = bitmapBuf;
  300. (*lplpbitmap)->numDWORD = hdr.numDWORDs;
  301. (*lplpbitmap)->bitmapsize = hdr.sizeinbits;
  302. } else {
  303. // bitmap not exist, create brand new
  304. *lplpbitmap = (LPCSC_BITMAP_U)malloc(sizeof(CSC_BITMAP_U));
  305. if (!(*lplpbitmap)) {
  306. // Error in memory allocation
  307. ret = -1;
  308. goto CLOSEFILE;
  309. }
  310. (*lplpbitmap)->bitmap = bitmapBuf;
  311. (*lplpbitmap)->numDWORD = hdr.numDWORDs;
  312. (*lplpbitmap)->bitmapsize = hdr.sizeinbits;
  313. }
  314. (*lplpbitmap)->reintProgress = 0; /* not reint yet */
  315. CLOSEFILE:
  316. CloseHandle(bitmapFile);
  317. return ret;
  318. }
  319. /*++
  320. CSC_BitmapReint()
  321. Routine Description:
  322. Copy a chunk of srcH to dstH. Offset depends on lpbitmap. Size of
  323. chunk depends on buffSize. May have to call several times to get
  324. srcH and dstH fully synchronized. lpbitmap remembers where the last
  325. CSC_BitmapReint call got to. See description of Return value below
  326. about how to know when to call again or stop calling.
  327. Arguments:
  328. lpbitmap the bitmap must not be zero, otherwise can't keep track of reint
  329. progress
  330. srcH the handle of the source file. See notes below
  331. dstH the handle of the destination file. See notes below
  332. buff user-supplied buffer
  333. buffSize size of the user-supplied buffer. See notes below
  334. lpbytesXfered Returns how many bytes are transferred, optional.
  335. Returns:
  336. CSC_BITMAPReintInvalid lpbitmap or buff is NULL, or srcH or dstH is invalid
  337. CSC_BITMAPReintError Error in transferring data
  338. CSC_BITMAPReintCont made some progress, call CSC_BITMAPReint again
  339. to continue Reint
  340. CSC_BITMAPReintDone Done Reint, don't need to call again
  341. Notes:
  342. srcH and dstH MUST NOT be opened with FILE_FLAG_OVERLAPPED
  343. or FILE_FLAG_NO_BUFFERING
  344. buffSize must be at least 2 times greater than BLOCKSIZE
  345. --*/
  346. int
  347. CSC_BitmapReint(
  348. LPCSC_BITMAP_U lpbitmap,
  349. HANDLE srcH,
  350. HANDLE dstH,
  351. LPVOID buff,
  352. DWORD buffSize,
  353. DWORD * lpbytesXfered)
  354. {
  355. DWORD bitoffset;
  356. DWORD DWORDoffset;
  357. DWORD bitmask;
  358. DWORD bytes2cpy = 0;
  359. DWORD bytesActuallyRead, bytesActuallyCopied;
  360. DWORD startFileOffset = 0;
  361. DWORD fileSize;
  362. BOOL seen1b4 = FALSE;
  363. int ret = CSC_BITMAPReintCont;
  364. if (lpbitmap == NULL || buff == NULL) {
  365. return CSC_BITMAPReintInvalid;
  366. }
  367. if (srcH == INVALID_HANDLE_VALUE || dstH == INVALID_HANDLE_VALUE) {
  368. return CSC_BITMAPReintInvalid;
  369. }
  370. CSC_BitmapKdPrint(
  371. REINT,
  372. ("***CSC_BitmapReint reintProgress: %u\n",
  373. lpbitmap->reintProgress));
  374. startFileOffset = lpbitmap->reintProgress;
  375. bitoffset = startFileOffset/BLOCKSIZE;
  376. startFileOffset = bitoffset * BLOCKSIZE; // make sure startFileOffset is
  377. // aligned with BLOCKSIZE
  378. DWORDoffset = bitoffset/(sizeof(DWORD)*8);
  379. bitmask = 1 << bitoffset%(sizeof(DWORD)*8);
  380. while (bytes2cpy < buffSize && bitoffset < lpbitmap->bitmapsize) {
  381. // the loop
  382. if ((bitmask & lpbitmap->bitmap[DWORDoffset]) != 0) {
  383. // the bit is marked
  384. if (!seen1b4) {
  385. // seeing first bit of a consecutive chunk of 1's
  386. startFileOffset = bitoffset * BLOCKSIZE;
  387. bytes2cpy += BLOCKSIZE;
  388. seen1b4 = TRUE;
  389. } else {
  390. // seeing the rest of the bits of a consecutive chunk of 1's
  391. // other than the first one
  392. bytes2cpy += BLOCKSIZE;
  393. }
  394. } else {
  395. // this bit is not marked
  396. if (seen1b4) {
  397. // first 0 after a chunk of consecutive 1's
  398. break;
  399. }
  400. }
  401. // Advance bitmap index
  402. bitoffset++;
  403. bitmask = bitmask << 1;
  404. if (bitmask == 0) {
  405. bitmask = 1;
  406. DWORDoffset++;
  407. }
  408. } // while
  409. if (bytes2cpy > buffSize) {
  410. bytes2cpy = buffSize;
  411. }
  412. // if never seen 1's then must have reached end of bitmap
  413. // Can't get Assert to compile!?
  414. // Assert(seen1b4 || (!seen1b4 && (bitoffset >= lpbitmap->bitmapsize)));
  415. /*
  416. CSC_BitmapKdPrint(
  417. REINT,
  418. ("Must be true, csc_bmpu.c, CSC_BitmapReint: %s\n",
  419. (seen1b4 || (!seen1b4 && (bitoffset >= lpbitmap->bitmapsize)))?
  420. "TRUE":"FALSE"));
  421. */
  422. CSC_BitmapKdPrint(
  423. REINT,
  424. ("startFileOffset: %u bytes2cpy: %u\n",
  425. startFileOffset,
  426. bytes2cpy));
  427. fileSize = GetFileSize(srcH, NULL);
  428. if (fileSize == 0xFFFFFFFF) {
  429. // if cannot get filesize, just be conservative on
  430. // what needs to be copied, ie, copy as much as possible
  431. if (seen1b4) {
  432. // Seen 1's before
  433. if (bitoffset >= lpbitmap->bitmapsize) {
  434. // copying until end of bitmap, copy as much as possible
  435. bytes2cpy = buffSize;
  436. }
  437. } else {
  438. // not seen 1's before, copy from the last block represented
  439. // by bitmap for as many bytes as possible
  440. startFileOffset = (lpbitmap->bitmapsize)? ((lpbitmap->bitmapsize-1)*BLOCKSIZE):0;
  441. bytes2cpy = buffSize;
  442. }
  443. } else { // filesize == 0xFFFFFFFF
  444. if (startFileOffset >= fileSize) {
  445. // Obviously done
  446. return CSC_BITMAPReintDone;
  447. }
  448. if (!seen1b4) {
  449. // never seen 1's
  450. if ((bitoffset * BLOCKSIZE) >= fileSize) {
  451. // bitmap is accurate representation of the file, or bitmap is larger
  452. // bitoffset should be pointing to last bit of the bitmap + 1
  453. // see ASSERT above
  454. return CSC_BITMAPReintDone;
  455. } else {
  456. // bitmap is shorter than the file, copy the rest of the file
  457. if (startFileOffset < lpbitmap->bitmapsize*BLOCKSIZE) {
  458. startFileOffset = (lpbitmap->bitmapsize)?
  459. ((lpbitmap->bitmapsize-1)*BLOCKSIZE):0;
  460. }
  461. bytes2cpy = fileSize - startFileOffset;
  462. if (bytes2cpy > buffSize) {
  463. bytes2cpy = buffSize;
  464. }
  465. }
  466. } else { // if !seen1b4
  467. // seen 1's
  468. if (bitoffset >= lpbitmap->bitmapsize) {
  469. // end of bitmap
  470. if (bitoffset * BLOCKSIZE < fileSize) {
  471. // bitmap is too small compared to real file
  472. bytes2cpy = fileSize - startFileOffset;
  473. if (bytes2cpy > buffSize) {
  474. bytes2cpy = buffSize;
  475. }
  476. } else {
  477. ret = CSC_BITMAPReintDone;
  478. }
  479. }
  480. }
  481. } // fileSize != 0xffffffff
  482. CSC_BitmapKdPrint(REINT, ("new startFileOffset: %u new bytes2cpy: %u\n",
  483. startFileOffset, bytes2cpy));
  484. //Assert(bytes2cpy <= buffSize);
  485. // Copy Contents
  486. //****** SET FILE POINTERS!!
  487. if (SetFilePointer(
  488. srcH,
  489. startFileOffset,
  490. NULL,
  491. FILE_BEGIN) == INVALID_SET_FILE_POINTER
  492. ) {
  493. return CSC_BITMAPReintError;
  494. }
  495. if (!ReadFile(srcH, buff, bytes2cpy, &bytesActuallyRead, NULL)) {
  496. return CSC_BITMAPReintError;
  497. }
  498. if (bytesActuallyRead > 0) {
  499. if (SetFilePointer(
  500. dstH,
  501. startFileOffset,
  502. NULL,
  503. FILE_BEGIN) == INVALID_SET_FILE_POINTER
  504. ) {
  505. return CSC_BITMAPReintError;
  506. }
  507. if (!WriteFile(
  508. dstH,
  509. buff,
  510. bytesActuallyRead,
  511. &bytesActuallyCopied, NULL)
  512. ) {
  513. return CSC_BITMAPReintError;
  514. }
  515. }
  516. // If copied all data or none read, done.
  517. if (
  518. (fileSize != 0xFFFFFFFF && (startFileOffset + bytesActuallyCopied) == fileSize)
  519. ||
  520. bytesActuallyRead == 0
  521. ) {
  522. ret = CSC_BITMAPReintDone;
  523. }
  524. CSC_BitmapKdPrint(
  525. REINT,
  526. ("bytesActuallyRead: %u bytesActuallyCopied: %u\n",
  527. bytesActuallyRead,
  528. bytesActuallyCopied));
  529. lpbitmap->reintProgress = startFileOffset + bytesActuallyCopied;
  530. CSC_BitmapKdPrint(
  531. REINT,
  532. ("***CSC_BitmapReint New reintProgress: %u\n",
  533. lpbitmap->reintProgress));
  534. if (lpbytesXfered) {
  535. *lpbytesXfered = bytesActuallyCopied;
  536. }
  537. return ret;
  538. }
  539. #ifdef DEBUG
  540. /*++
  541. CSC_BitmapOutput()
  542. Routine Description:
  543. Outputs the passed in bitmap to kd
  544. Arguments:
  545. Returns:
  546. Notes:
  547. --*/
  548. VOID
  549. CSC_BitmapOutput(
  550. LPCSC_BITMAP_U lpbitmap)
  551. {
  552. DWORD i;
  553. if (lpbitmap == NULL) {
  554. CSC_BitmapKdPrint( PRINTBITMAP, ("lpbitmap is NULL\n"));
  555. return;
  556. }
  557. CSC_BitmapKdPrint(
  558. PRINTBITMAP,
  559. ( "lpbitmap 0x%08x, bitmapsize 0x%x (%u) bits, numDWORD 0x%x (%u)\n",
  560. lpbitmap,
  561. lpbitmap->bitmapsize,
  562. lpbitmap->bitmapsize,
  563. lpbitmap->numDWORD,
  564. lpbitmap->numDWORD));
  565. CSC_BitmapKdPrint(
  566. PRINTBITMAP,
  567. ( "bitmap |0/5 |1/6 |2/7 |3/8 |4/9\n"));
  568. CSC_BitmapKdPrint(
  569. PRINTBITMAP,
  570. ("number |01234|56789|01234|56789|01234|56789|01234|56789|01234|56789"));
  571. for (i = 0; i < lpbitmap->bitmapsize; i++) {
  572. if ((i % 50) == 0)
  573. CSC_BitmapKdPrint(PRINTBITMAP, ( "\n%08d", i));
  574. if ((i % 5) == 0)
  575. CSC_BitmapKdPrint(PRINTBITMAP, ( "|"));
  576. CSC_BitmapKdPrint(
  577. PRINTBITMAP,
  578. ( "%1d", CSC_BitmapIsMarked(lpbitmap, i)));
  579. }
  580. CSC_BitmapKdPrint(PRINTBITMAP, ( "\n"));
  581. }
  582. #endif