test: cmwrapr.c File Reference

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

# cmwrapr.c File Reference

`#include "cmp.h"`

Go to the source code of this file.

## Defines

#define | MAX_FILE_IO 0x10000
#define | CmpIoFileRead 1
#define | CmpIoFileWrite 2
#define | CmpIoFileSetSize 3
#define | CmpIoFileFlush 4

## Functions

PVOID | CmpAllocate (ULONG Size, BOOLEAN UseForIo)
VOID | CmpFree (PVOID MemoryBlock, ULONG GlobalQuotaSize)
NTSTATUS | CmpDoFileSetSize (PHHIVE Hive, ULONG FileType, ULONG FileSize)
NTSTATUS | CmpCreateEvent (IN EVENT_TYPE eventType, OUT PHANDLE eventHandle, OUT PKEVENT *event)
BOOLEAN | CmpFileRead (PHHIVE Hive, ULONG FileType, PULONG FileOffset, PVOID DataBuffer, ULONG DataLength)
BOOLEAN | CmpFileWrite (PHHIVE Hive, ULONG FileType, PCMP_OFFSET_ARRAY offsetArray, ULONG offsetArrayCount, PULONG FileOffset)
BOOLEAN | CmpFileFlush (PHHIVE Hive, ULONG FileType)

## Variables

ULONG | perftouchbuffer = 0
BOOLEAN | CmpNoWrite
struct {
ULONG Action
HANDLE Handle
NTSTATUS Status
} | CmRegistryIODebug

## Define Documentation

#define CmpIoFileFlush 4

| Definition at line 49 of file cmwrapr.c. Referenced by CmpFileFlush().

#define CmpIoFileRead 1

| Definition at line 46 of file cmwrapr.c. Referenced by CmpFileRead().

#define CmpIoFileSetSize 3

| Definition at line 48 of file cmwrapr.c. Referenced by CmpDoFileSetSize().

#define CmpIoFileWrite 2

| Definition at line 47 of file cmwrapr.c. Referenced by CmpFileWrite().

#define MAX_FILE_IO 0x10000

| Definition at line 44 of file cmwrapr.c. Referenced by CmpFileRead(), and CmpFileWrite().

## Function Documentation

PVOID CmpAllocate | ( | ULONG | Size,
|  | BOOLEAN | UseForIo
| ) |

Definition at line 62 of file cmwrapr.c.

References CML_MINOR, CMLOG, CmpClaimGlobalQuota(), CmpReleaseGlobalQuota(), CMS_POOL, ExAllocatePoolWithTag, FALSE, NULL, PagedPool, PagedPoolCacheAligned, RtlGetCallersAddress(), and Size.

Referenced by CmpInitializeHive().

    00068                    :
    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 }

NTSTATUS CmpCreateEvent | ( | IN EVENT_TYPE | eventType,
|  | OUT PHANDLE | eventHandle,
|  | OUT PKEVENT * | event
| ) |

Definition at line 313 of file cmwrapr.c.

References FALSE, KernelMode, NT_SUCCESS, NTSTATUS(), NULL, and ObReferenceObjectByHandle().

Referenced by CmpFileRead(), CmpFileWrite(), and CmpOpenHiveFiles().

    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 }

NTSTATUS CmpDoFileSetSize | ( | PHHIVE | Hive,
|  | ULONG | FileType,
|  | ULONG | FileSize
| ) |

Definition at line 227 of file cmwrapr.c.

References ASSERT, ASSERT_PASSIVE_LEVEL, CmpIoFileSetSize, CmRegistryIODebug, DbgPrint, FALSE, _CMHIVE::FileHandles, Hive, IoSetThreadHardErrorMode(), L, NT_SUCCESS, NTSTATUS(), NULL, Status, TRUE, and ZwSetInformationFile().

Referenced by CmpFileSetSize(), CmpWorker(), CmpWorkerCommand(), HvpDoWriteHive(), and HvWriteHive().

    00234                    :
    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 }

BOOLEAN CmpFileFlush | ( | PHHIVE | Hive,
|  | ULONG | FileType
| ) |

Definition at line 772 of file cmwrapr.c.

References ASSERT, ASSERT_PASSIVE_LEVEL, CML_MAJOR, CMLOG, CmpIoFileFlush, CmpNoWrite, CmRegistryIODebug, CMS_IO, DbgPrint, FALSE, _CMHIVE::FileHandles, Hive, NT_SUCCESS, NTSTATUS(), NULL, and TRUE.

Referenced by CmpInitializeHive(), and CmpSaveKeyByFileCopy().

    00778                    :
    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 }
    }

BOOLEAN CmpFileRead | ( | PHHIVE | Hive,
|  | ULONG | FileType,
|  | PULONG | FileOffset,
|  | PVOID | DataBuffer,
|  | ULONG | DataLength
| ) |

Definition at line 351 of file cmwrapr.c.

References ASSERT, ASSERT_PASSIVE_LEVEL, CML_MAJOR, CMLOG, CmpCreateEvent(), CmpIoFileRead, CmRegistryIODebug, CMS_IO, CMS_IO_ERROR, DbgPrint, Executive, FALSE, _CMHIVE::FileHandles, Hive, KernelMode, KeWaitForSingleObject(), L, MAX_FILE_IO, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, Offset, and TRUE.

Referenced by CmpInitializeHive(), and CmpWorker().

    00360                    :
    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 }

BOOLEAN CmpFileWrite | ( | PHHIVE | Hive,
|  | ULONG | FileType,
|  | PCMP_OFFSET_ARRAY | offsetArray,
|  | ULONG | offsetArrayCount,
|  | PULONG | FileOffset
| ) |

Definition at line 516 of file cmwrapr.c.

References ASSERT, ASSERT_PASSIVE_LEVEL, CML_MAJOR, CMLOG, CmpCreateEvent(), CmpIoFileWrite, CmpNoWrite, CmRegistryIODebug, CMS_IO, CMS_IO_ERROR, DbgPrint, Executive, FALSE, _CMHIVE::FileHandles, Hive, KernelMode, KeWaitForMultipleObjects(), L, MAX_FILE_IO, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, Offset, PAGE_SIZE, perftouchbuffer, Status, and TRUE.

Referenced by CmpInitializeHive(), and CmpSaveKeyByFileCopy().

    00525                    :
    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 }

VOID CmpFree | ( | PVOID | MemoryBlock,
|  | ULONG | GlobalQuotaSize
| ) |

Definition at line 186 of file cmwrapr.c.

References ASSERT, CML_MINOR, CMLOG, CmpReleaseGlobalQuota(), CMS_POOL, ExFreePool(), and RtlGetCallersAddress().

Referenced by CmpDestroyTemporaryHive(), CmpInitializeHive(), CmpValidateAlternate(), CmReplaceKey(), CmUnloadKey(), EhCloseHive(), HvFreeHive(), HvFreeHivePartial(), and HvWriteHive().

    00192                    :
    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 }

## Variable Documentation

ULONG Action

| Definition at line 52 of file cmwrapr.c.

BOOLEAN CmpNoWrite

| Definition at line 38 of file cmwrapr.c.

struct { ... } CmRegistryIODebug

HANDLE Handle

| Definition at line 53 of file cmwrapr.c.

ULONG perftouchbuffer = 0

| Definition at line 24 of file cmwrapr.c. Referenced by CmpFileWrite().

NTSTATUS Status

| Definition at line 54 of file cmwrapr.c.