Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cmwrapr.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1991 Microsoft Corporation 00004 00005 Module Name: 00006 00007 cmwrapr.c 00008 00009 Abstract: 00010 00011 This module contains the source for wrapper routines called by the 00012 hive code, which in turn call the appropriate NT routines. 00013 00014 Author: 00015 00016 Bryan M. Willman (bryanwi) 16-Dec-1991 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "cmp.h" 00023 00024 ULONG perftouchbuffer = 0; 00025 00026 #ifdef ALLOC_PRAGMA 00027 #pragma alloc_text(PAGE,CmpAllocate) 00028 #ifdef POOL_TAGGING 00029 #pragma alloc_text(PAGE,CmpAllocateTag) 00030 #endif 00031 #pragma alloc_text(PAGE,CmpFree) 00032 #pragma alloc_text(PAGE,CmpDoFileSetSize) 00033 #pragma alloc_text(PAGE,CmpFileRead) 00034 #pragma alloc_text(PAGE,CmpFileWrite) 00035 #pragma alloc_text(PAGE,CmpFileFlush) 00036 #endif 00037 00038 extern BOOLEAN CmpNoWrite; 00039 00040 // 00041 // never read more than 64k, neither the filesystem nor some disk drivers 00042 // like it much. 00043 // 00044 #define MAX_FILE_IO 0x10000 00045 00046 #define CmpIoFileRead 1 00047 #define CmpIoFileWrite 2 00048 #define CmpIoFileSetSize 3 00049 #define CmpIoFileFlush 4 00050 00051 extern struct { 00052 ULONG Action; 00053 HANDLE Handle; 00054 NTSTATUS Status; 00055 } CmRegistryIODebug; 00056 00057 // 00058 // Storage management 00059 // 00060 00061 PVOID 00062 CmpAllocate( 00063 ULONG Size, 00064 BOOLEAN UseForIo 00065 ) 00066 /*++ 00067 00068 Routine Description: 00069 00070 This routine makes more memory available to a hive. 00071 00072 It is environment specific. 00073 00074 Arguments: 00075 00076 Size - amount of space caller wants 00077 00078 UseForIo - TRUE if object allocated will be target of I/O, 00079 FALSE if not. 00080 00081 Return Value: 00082 00083 NULL if failure, address of allocated block if not. 00084 00085 --*/ 00086 { 00087 PVOID result; 00088 ULONG pooltype; 00089 #if DBG 00090 PVOID Caller; 00091 PVOID CallerCaller; 00092 RtlGetCallersAddress(&Caller, &CallerCaller); 00093 #endif 00094 00095 if (CmpClaimGlobalQuota(Size) == FALSE) { 00096 return NULL; 00097 } 00098 00099 pooltype = (UseForIo) ? PagedPoolCacheAligned : PagedPool; 00100 result = ExAllocatePoolWithTag( 00101 pooltype, 00102 Size, 00103 CM_POOL_TAG 00104 ); 00105 00106 #if DBG 00107 CMLOG(CML_MINOR, CMS_POOL) { 00108 KdPrint(("**CmpAllocate: allocate:%08lx, ", Size)); 00109 KdPrint(("type:%d, at:%08lx ", PagedPool, result)); 00110 KdPrint(("c:%08lx cc:%08lx\n", Caller, CallerCaller)); 00111 } 00112 #endif 00113 00114 if (result == NULL) { 00115 CmpReleaseGlobalQuota(Size); 00116 } 00117 00118 return result; 00119 } 00120 00121 #ifdef POOL_TAGGING 00122 PVOID 00123 CmpAllocateTag( 00124 ULONG Size, 00125 BOOLEAN UseForIo, 00126 ULONG Tag 00127 ) 00128 /*++ 00129 00130 Routine Description: 00131 00132 This routine makes more memory available to a hive. 00133 00134 It is environment specific. 00135 00136 Arguments: 00137 00138 Size - amount of space caller wants 00139 00140 UseForIo - TRUE if object allocated will be target of I/O, 00141 FALSE if not. 00142 00143 Return Value: 00144 00145 NULL if failure, address of allocated block if not. 00146 00147 --*/ 00148 { 00149 PVOID result; 00150 ULONG pooltype; 00151 #if DBG 00152 PVOID Caller; 00153 PVOID CallerCaller; 00154 RtlGetCallersAddress(&Caller, &CallerCaller); 00155 #endif 00156 00157 if (CmpClaimGlobalQuota(Size) == FALSE) { 00158 return NULL; 00159 } 00160 00161 pooltype = (UseForIo) ? PagedPoolCacheAligned : PagedPool; 00162 result = ExAllocatePoolWithTag( 00163 pooltype, 00164 Size, 00165 Tag 00166 ); 00167 00168 #if DBG 00169 CMLOG(CML_MINOR, CMS_POOL) { 00170 KdPrint(("**CmpAllocate: allocate:%08lx, ", Size)); 00171 KdPrint(("type:%d, at:%08lx ", PagedPool, result)); 00172 KdPrint(("c:%08lx cc:%08lx\n", Caller, CallerCaller)); 00173 } 00174 #endif 00175 00176 if (result == NULL) { 00177 CmpReleaseGlobalQuota(Size); 00178 } 00179 00180 return result; 00181 } 00182 #endif 00183 00184 00185 VOID 00186 CmpFree( 00187 PVOID MemoryBlock, 00188 ULONG GlobalQuotaSize 00189 ) 00190 /*++ 00191 00192 Routine Description: 00193 00194 This routine frees memory that has been allocated by the registry. 00195 00196 It is environment specific 00197 00198 00199 Arguments: 00200 00201 MemoryBlock - supplies address of memory object to free 00202 00203 GlobalQuotaSize - amount of global quota to release 00204 00205 Return Value: 00206 00207 NONE 00208 00209 --*/ 00210 { 00211 #if DBG 00212 PVOID Caller; 00213 PVOID CallerCaller; 00214 RtlGetCallersAddress(&Caller, &CallerCaller); 00215 CMLOG(CML_MINOR, CMS_POOL) { 00216 KdPrint(("**FREEING:%08lx c,cc:%08lx,%08lx\n", MemoryBlock, Caller, CallerCaller)); 00217 } 00218 #endif 00219 ASSERT(GlobalQuotaSize > 0); 00220 CmpReleaseGlobalQuota(GlobalQuotaSize); 00221 ExFreePool(MemoryBlock); 00222 return; 00223 } 00224 00225 00226 NTSTATUS 00227 CmpDoFileSetSize( 00228 PHHIVE Hive, 00229 ULONG FileType, 00230 ULONG FileSize 00231 ) 00232 /*++ 00233 00234 Routine Description: 00235 00236 This routine sets the size of a file. It must not return until 00237 the size is guaranteed. 00238 00239 It is environment specific. 00240 00241 Must be running in the context of the cmp worker thread. 00242 00243 Arguments: 00244 00245 Hive - Hive we are doing I/O for 00246 00247 FileType - which supporting file to use 00248 00249 FileSize - 32 bit value to set the file's size to 00250 00251 Return Value: 00252 00253 FALSE if failure 00254 TRUE if success 00255 00256 --*/ 00257 { 00258 PCMHIVE CmHive; 00259 HANDLE FileHandle; 00260 NTSTATUS Status; 00261 FILE_END_OF_FILE_INFORMATION FileInfo; 00262 IO_STATUS_BLOCK IoStatus; 00263 BOOLEAN oldFlag; 00264 00265 ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0); 00266 00267 CmHive = (PCMHIVE)Hive; 00268 FileHandle = CmHive->FileHandles[FileType]; 00269 if (FileHandle == NULL) { 00270 return TRUE; 00271 } 00272 00273 // 00274 // disable hard error popups, to avoid self deadlock on bogus devices 00275 // 00276 oldFlag = IoSetThreadHardErrorMode(FALSE); 00277 00278 FileInfo.EndOfFile.HighPart = 0L; 00279 FileInfo.EndOfFile.LowPart = FileSize; 00280 00281 ASSERT_PASSIVE_LEVEL(); 00282 00283 Status = ZwSetInformationFile( 00284 FileHandle, 00285 &IoStatus, 00286 (PVOID)&FileInfo, 00287 sizeof(FILE_END_OF_FILE_INFORMATION), 00288 FileEndOfFileInformation 00289 ); 00290 00291 if (NT_SUCCESS(Status)) { 00292 ASSERT(IoStatus.Status == Status); 00293 } else { 00294 00295 // 00296 // set debugging info 00297 // 00298 CmRegistryIODebug.Action = CmpIoFileSetSize; 00299 CmRegistryIODebug.Handle = FileHandle; 00300 CmRegistryIODebug.Status = Status; 00301 DbgPrint("CmpFileSetSize:\tHandle=%08lx NewLength=%08lx \n", FileHandle, FileSize); 00302 } 00303 00304 // 00305 // restore hard error popups mode 00306 // 00307 IoSetThreadHardErrorMode(oldFlag); 00308 00309 return Status; 00310 } 00311 00312 NTSTATUS 00313 CmpCreateEvent( 00314 IN EVENT_TYPE eventType, 00315 OUT PHANDLE eventHandle, 00316 OUT PKEVENT *event 00317 ) 00318 { 00319 NTSTATUS status; 00320 OBJECT_ATTRIBUTES obja; 00321 00322 InitializeObjectAttributes( &obja, NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); 00323 status = ZwCreateEvent( 00324 eventHandle, 00325 EVENT_ALL_ACCESS, 00326 &obja, 00327 eventType, 00328 FALSE); 00329 00330 if (!NT_SUCCESS(status)) { 00331 return status; 00332 } 00333 00334 status = ObReferenceObjectByHandle( 00335 *eventHandle, 00336 EVENT_ALL_ACCESS, 00337 NULL, 00338 KernelMode, 00339 event, 00340 NULL); 00341 00342 if (!NT_SUCCESS(status)) { 00343 ZwClose(*eventHandle); 00344 return status; 00345 } 00346 return status; 00347 } 00348 00349 00350 BOOLEAN 00351 CmpFileRead ( 00352 PHHIVE Hive, 00353 ULONG FileType, 00354 PULONG FileOffset, 00355 PVOID DataBuffer, 00356 ULONG DataLength 00357 ) 00358 /*++ 00359 00360 Routine Description: 00361 00362 This routine reads in a buffer from a file. 00363 00364 It is environment specific. 00365 00366 NOTE: We assume the handle is opened for asynchronous access, 00367 and that we, and not the IO system, are keeping the 00368 offset pointer. 00369 00370 NOTE: Only 32bit offsets are supported, even though the underlying 00371 IO system on NT supports 64 bit offsets. 00372 00373 Arguments: 00374 00375 Hive - Hive we are doing I/O for 00376 00377 FileType - which supporting file to use 00378 00379 FileOffset - pointer to variable providing 32bit offset on input, 00380 and receiving new 32bit offset on output. 00381 00382 DataBuffer - pointer to buffer 00383 00384 DataLength - length of buffer 00385 00386 Return Value: 00387 00388 FALSE if failure 00389 TRUE if success 00390 00391 --*/ 00392 { 00393 NTSTATUS status; 00394 LARGE_INTEGER Offset; 00395 IO_STATUS_BLOCK IoStatus; 00396 PCMHIVE CmHive; 00397 HANDLE FileHandle; 00398 ULONG LengthToRead; 00399 HANDLE eventHandle = NULL; 00400 PKEVENT eventObject = NULL; 00401 00402 ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0); 00403 CmHive = (PCMHIVE)Hive; 00404 FileHandle = CmHive->FileHandles[FileType]; 00405 if (FileHandle == NULL) { 00406 return TRUE; 00407 } 00408 00409 CMLOG(CML_MAJOR, CMS_IO) { 00410 KdPrint(("CmpFileRead:\n")); 00411 KdPrint(("\tHandle=%08lx Offset=%08lx ", FileHandle, *FileOffset)); 00412 KdPrint(("Buffer=%08lx Length=%08lx\n", DataBuffer, DataLength)); 00413 } 00414 00415 // 00416 // Detect attempt to read off end of 2gig file (this should be irrelevent) 00417 // 00418 if ((0xffffffff - *FileOffset) < DataLength) { 00419 CMLOG(CML_MAJOR, CMS_IO_ERROR) KdPrint(("CmpFileRead: runoff\n")); 00420 return FALSE; 00421 } 00422 00423 status = CmpCreateEvent( 00424 SynchronizationEvent, 00425 &eventHandle, 00426 &eventObject); 00427 if (!NT_SUCCESS(status)) 00428 return FALSE; 00429 00430 // 00431 // We'd really like to just call the filesystems and have them do 00432 // the right thing. But the filesystem will attempt to lock our 00433 // entire buffer into memory, and that may fail for large requests. 00434 // So we split our reads into 64k chunks and call the filesystem for 00435 // each one. 00436 // 00437 ASSERT_PASSIVE_LEVEL(); 00438 while (DataLength > 0) { 00439 00440 // 00441 // Convert ULONG to Large 00442 // 00443 Offset.LowPart = *FileOffset; 00444 Offset.HighPart = 0L; 00445 00446 // 00447 // trim request down if necessary. 00448 // 00449 if (DataLength > MAX_FILE_IO) { 00450 LengthToRead = MAX_FILE_IO; 00451 } else { 00452 LengthToRead = DataLength; 00453 } 00454 00455 status = ZwReadFile( 00456 FileHandle, 00457 eventHandle, 00458 NULL, // apcroutine 00459 NULL, // apccontext 00460 &IoStatus, 00461 DataBuffer, 00462 LengthToRead, 00463 &Offset, 00464 NULL // key 00465 ); 00466 00467 if (STATUS_PENDING == status) { 00468 status = KeWaitForSingleObject(eventObject, Executive, 00469 KernelMode, FALSE, NULL); 00470 ASSERT(STATUS_SUCCESS == status); 00471 status = IoStatus.Status; 00472 } 00473 00474 // 00475 // adjust offsets 00476 // 00477 *FileOffset = Offset.LowPart + LengthToRead; 00478 DataLength -= LengthToRead; 00479 (PUCHAR)DataBuffer += LengthToRead; 00480 00481 if (NT_SUCCESS(status)) { 00482 ASSERT(IoStatus.Status == status); 00483 if (IoStatus.Information != LengthToRead) { 00484 CMLOG(CML_MAJOR, CMS_IO_ERROR) { 00485 KdPrint(("CmpFileRead:\n\t")); 00486 KdPrint(("Failure1: status = %08lx ", status)); 00487 KdPrint(("IoInformation = %08lx\n", IoStatus.Information)); 00488 } 00489 ObDereferenceObject(eventObject); 00490 ZwClose(eventHandle); 00491 return FALSE; 00492 } 00493 } else { 00494 // 00495 // set debugging info 00496 // 00497 CmRegistryIODebug.Action = CmpIoFileRead; 00498 CmRegistryIODebug.Handle = FileHandle; 00499 CmRegistryIODebug.Status = status; 00500 DbgPrint("CmpFileRead:\tFailure2: status = %08lx IoStatus = %08lx\n", status, IoStatus.Status); 00501 00502 ObDereferenceObject(eventObject); 00503 ZwClose(eventHandle); 00504 return FALSE; 00505 } 00506 00507 } 00508 ObDereferenceObject(eventObject); 00509 ZwClose(eventHandle); 00510 return TRUE; 00511 } 00512 00513 00514 00515 BOOLEAN 00516 CmpFileWrite( 00517 PHHIVE Hive, 00518 ULONG FileType, 00519 PCMP_OFFSET_ARRAY offsetArray, 00520 ULONG offsetArrayCount, 00521 PULONG FileOffset 00522 ) 00523 /*++ 00524 00525 Routine Description: 00526 00527 This routine writes an array of buffers out to a file. 00528 00529 It is environment specific. 00530 00531 NOTE: We assume the handle is opened for asynchronous access, 00532 and that we, and not the IO system, are keeping the 00533 offset pointer. 00534 00535 NOTE: Only 32bit offsets are supported, even though the underlying 00536 IO system on NT supports 64 bit offsets. 00537 00538 Arguments: 00539 00540 Hive - Hive we are doing I/O for 00541 00542 FileType - which supporting file to use 00543 00544 offsetArray - array of structures where each structure holds a 32bit offset 00545 into the Hive file and pointer the a buffer written to that 00546 file offset. 00547 00548 offsetArrayCount - number of elements in the offsetArray. 00549 00550 FileOffset - returns the file offset after the last write to the file. 00551 00552 Return Value: 00553 00554 FALSE if failure 00555 TRUE if success 00556 00557 --*/ 00558 { 00559 NTSTATUS status; 00560 LARGE_INTEGER Offset; 00561 PCMHIVE CmHive; 00562 HANDLE FileHandle; 00563 ULONG LengthToWrite; 00564 LONG WaitBufferCount = 0; 00565 LONG idx; 00566 ULONG arrayCount = 0; 00567 PVOID DataBuffer; 00568 ULONG DataLength; 00569 HANDLE eventHandles[MAXIMUM_WAIT_OBJECTS]; 00570 PKEVENT eventObjects[MAXIMUM_WAIT_OBJECTS]; 00571 KWAIT_BLOCK waitBlockArray[MAXIMUM_WAIT_OBJECTS]; 00572 IO_STATUS_BLOCK IoStatus[MAXIMUM_WAIT_OBJECTS]; 00573 BOOLEAN ret_val = TRUE; 00574 00575 if (CmpNoWrite) { 00576 return TRUE; 00577 } 00578 00579 ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0); 00580 CmHive = (PCMHIVE)Hive; 00581 FileHandle = CmHive->FileHandles[FileType]; 00582 if (FileHandle == NULL) { 00583 return TRUE; 00584 } 00585 00586 CMLOG(CML_MAJOR, CMS_IO) { 00587 KdPrint(("CmpFileWrite:\n")); 00588 KdPrint(("\tHandle=%08lx ", FileHandle)); 00589 } 00590 00591 for (idx = 0; idx < MAXIMUM_WAIT_OBJECTS; idx++) { 00592 eventHandles[idx] = NULL; 00593 } 00594 00595 // Bring pages being written into memory first to allow disk to write 00596 // buffer contiguously. 00597 for (idx = 0; (ULONG) idx < offsetArrayCount; idx++) { 00598 char * start = offsetArray[idx].DataBuffer; 00599 char * end = (char *) start + offsetArray[idx].DataLength; 00600 while (start < end) { 00601 // perftouchbuffer globally declared so that compiler won't try 00602 // to remove it and this loop (if its smart enough?). 00603 perftouchbuffer += (ULONG) *start; 00604 start += PAGE_SIZE; 00605 } 00606 } 00607 00608 // 00609 // We'd really like to just call the filesystems and have them do 00610 // the right thing. But the filesystem will attempt to lock our 00611 // entire buffer into memory, and that may fail for large requests. 00612 // So we split our reads into 64k chunks and call the filesystem for 00613 // each one. 00614 // 00615 ASSERT_PASSIVE_LEVEL(); 00616 arrayCount = 0; 00617 DataLength = 0; 00618 // This outer loop is hit more than once if the MAXIMUM_WAIT_OBJECTS limit 00619 // is hit before the offset array is drained. 00620 while (arrayCount < offsetArrayCount) { 00621 WaitBufferCount = 0; 00622 00623 // This loop fills the wait buffer. 00624 while ((arrayCount < offsetArrayCount) && 00625 (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) { 00626 00627 // If data length isn't zero than the wait buffer filled before the 00628 // buffer in the last offsetArray element was sent to write file. 00629 if (DataLength == 0) { 00630 *FileOffset = offsetArray[arrayCount].FileOffset; 00631 DataBuffer = offsetArray[arrayCount].DataBuffer; 00632 DataLength = offsetArray[arrayCount].DataLength; 00633 // 00634 // Detect attempt to read off end of 2gig file 00635 // (this should be irrelevent) 00636 // 00637 if ((0xffffffff - *FileOffset) < DataLength) { 00638 CMLOG(CML_MAJOR, CMS_IO_ERROR) KdPrint(("CmpFileWrite: runoff\n")); 00639 goto Error_Exit; 00640 } 00641 } 00642 // else still more to write out of last buffer. 00643 00644 while ((DataLength > 0) && (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) { 00645 00646 // 00647 // Convert ULONG to Large 00648 // 00649 Offset.LowPart = *FileOffset; 00650 Offset.HighPart = 0L; 00651 00652 // 00653 // trim request down if necessary. 00654 // 00655 if (DataLength > MAX_FILE_IO) { 00656 LengthToWrite = MAX_FILE_IO; 00657 } else { 00658 LengthToWrite = DataLength; 00659 } 00660 00661 // Previously created events are reused. 00662 if (eventHandles[WaitBufferCount] == NULL) { 00663 status = CmpCreateEvent(SynchronizationEvent, 00664 &eventHandles[WaitBufferCount], 00665 &eventObjects[WaitBufferCount]); 00666 if (!NT_SUCCESS(status)) { 00667 // Make sure we don't try to clean this up. 00668 eventHandles[WaitBufferCount] = NULL; 00669 goto Error_Exit; 00670 } 00671 } 00672 00673 status = ZwWriteFile(FileHandle, 00674 eventHandles[WaitBufferCount], 00675 NULL, // apcroutine 00676 NULL, // apccontext 00677 &IoStatus[WaitBufferCount], 00678 DataBuffer, 00679 LengthToWrite, 00680 &Offset, 00681 NULL); 00682 00683 if (!NT_SUCCESS(status)) { 00684 goto Error_Exit; 00685 } 00686 00687 WaitBufferCount++; 00688 00689 // 00690 // adjust offsets 00691 // 00692 *FileOffset = Offset.LowPart + LengthToWrite; 00693 DataLength -= LengthToWrite; 00694 (PUCHAR)DataBuffer += LengthToWrite; 00695 } // while (DataLength > 0 && WaitBufferCount < MAXIMUM_WAIT_OBJECTS) 00696 00697 arrayCount++; 00698 00699 } // while (arrayCount < offsetArrayCount && 00700 // WaitBufferCount < MAXIMUM_WAIT_OBJECTS) 00701 00702 status = KeWaitForMultipleObjects(WaitBufferCount, 00703 eventObjects, 00704 WaitAll, 00705 Executive, 00706 KernelMode, 00707 FALSE, 00708 NULL, 00709 waitBlockArray); 00710 00711 if (!NT_SUCCESS(status)) 00712 goto Error_Exit; 00713 00714 for (idx = 0; idx < WaitBufferCount; idx++) { 00715 if (!NT_SUCCESS(IoStatus[idx].Status)) { 00716 ret_val = FALSE; 00717 goto Done; 00718 } 00719 } 00720 00721 // There may still be more to do if the last element held a big buffer 00722 // and the wait buffer filled before it was all sent to the file. 00723 if (DataLength > 0) { 00724 arrayCount--; 00725 } 00726 00727 } // while (arrayCount < offsetArrayCount) 00728 00729 ret_val = TRUE; 00730 00731 goto Done; 00732 Error_Exit: 00733 // 00734 // set debugging info 00735 // 00736 CmRegistryIODebug.Action = CmpIoFileWrite; 00737 CmRegistryIODebug.Handle = FileHandle; 00738 CmRegistryIODebug.Status = status; 00739 DbgPrint("CmpFileWrite: error exiting %d\n", status); 00740 // 00741 // if WaitBufferCount > 0 then we have successfully issued 00742 // some I/Os, but not all of them. This is an error, but we 00743 // cannot return from this routine until all the successfully 00744 // issued I/Os have completed. 00745 // 00746 if (WaitBufferCount > 0) { 00747 status = KeWaitForMultipleObjects(WaitBufferCount, 00748 eventObjects, 00749 WaitAll, 00750 Executive, 00751 KernelMode, 00752 FALSE, 00753 NULL, 00754 waitBlockArray); 00755 } 00756 00757 00758 ret_val = FALSE; 00759 Done: 00760 idx = 0; 00761 // Clean up open event handles and objects. 00762 while ((idx < MAXIMUM_WAIT_OBJECTS) && (eventHandles[idx] != NULL)) { 00763 ObDereferenceObject(eventObjects[idx]); 00764 ZwClose(eventHandles[idx]); 00765 idx++; 00766 } 00767 return ret_val; 00768 } 00769 00770 00771 BOOLEAN 00772 CmpFileFlush ( 00773 PHHIVE Hive, 00774 ULONG FileType 00775 ) 00776 /*++ 00777 00778 Routine Description: 00779 00780 This routine performs a flush on a file handle. 00781 00782 Arguments: 00783 00784 Hive - Hive we are doing I/O for 00785 00786 FileType - which supporting file to use 00787 00788 Return Value: 00789 00790 FALSE if failure 00791 TRUE if success 00792 00793 --*/ 00794 { 00795 NTSTATUS status; 00796 IO_STATUS_BLOCK IoStatus; 00797 PCMHIVE CmHive; 00798 HANDLE FileHandle; 00799 00800 ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0); 00801 CmHive = (PCMHIVE)Hive; 00802 FileHandle = CmHive->FileHandles[FileType]; 00803 if (FileHandle == NULL) { 00804 return TRUE; 00805 } 00806 00807 if (CmpNoWrite) { 00808 return TRUE; 00809 } 00810 00811 CMLOG(CML_MAJOR, CMS_IO) { 00812 KdPrint(("CmpFileFlush:\n\tHandle = %08lx\n", FileHandle)); 00813 } 00814 00815 ASSERT_PASSIVE_LEVEL(); 00816 00817 status = ZwFlushBuffersFile( 00818 FileHandle, 00819 &IoStatus 00820 ); 00821 00822 if (NT_SUCCESS(status)) { 00823 ASSERT(IoStatus.Status == status); 00824 return TRUE; 00825 } else { 00826 // 00827 // set debugging info 00828 // 00829 CmRegistryIODebug.Action = CmpIoFileFlush; 00830 CmRegistryIODebug.Handle = FileHandle; 00831 CmRegistryIODebug.Status = status; 00832 DbgPrint("CmpFileFlush:\tFailure1: status = %08lx IoStatus = %08lx\n",status,IoStatus.Status); 00833 return FALSE; 00834 } 00835 return TRUE; 00836 }

Generated on Sat May 15 19:39:29 2004 for test by doxygen 1.3.7