test: rtlinit.c Source File

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

# rtlinit.c

Go to the documentation of this file.

    00001 /****************************** Module Header ******************************\
    00002 * Module Name: rtlinit.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * This module contains all the init code for the USERRTL.DLL.  When the DLL is
    00007 * dynlinked its initialization procedure (UserRtlDllInitialize) is called by
    00008 * the loader.
    00009 *
    00010 * History:
    00011 * 14-Jan-1991 mikeke
    00012 \***************************************************************************/
    00013
    00014 #define MOVE_TO_RTL
    00015
    00016 #include "precomp.h"
    00017 #pragma hdrstop
    00018 #include "ntimage.h"
    00019
    00020
    00021 /**************************************************************************\
    00022 * RtlCaptureAnsiString
    00023 *
    00024 * Converts a NULL-terminated ANSI string into a counted
    00025 * unicode string.
    00026 *
    00027 * 03-22-95 JimA         Created.
    00028 \**************************************************************************/
    00029
    00030 BOOL RtlCaptureAnsiString(
    00031     PIN_STRING pstr,
    00032     LPCSTR psz,
    00033     BOOL fForceAlloc)
    00034 {
    00035     int cbSrc;
    00036     int cbDst;
    00037
    00038     pstr->fAllocated = FALSE;
    00039     if (psz) {
    00040         cbSrc = strlen(psz) + 1;
    00041         if (cbSrc > MAXUSHORT) {
    00042             RIPMSG0(RIP_WARNING, "String too long for standard string");
    00043             return FALSE;
    00044         }
    00045
    00046         /*
    00047          * If the allocation is forced or if the string is
    00048          * too long to fit in the TEB, allocate a buffer.
    00049          * Otherwise, store the result in the TEB.
    00050          */
    00051         if (fForceAlloc ||
    00052                 cbSrc > (STATIC_UNICODE_BUFFER_LENGTH / sizeof(WCHAR))) {
    00053             pstr->strCapture.Buffer = RtlAllocateHeap(pUserHeap,
    00054                     0, cbSrc * sizeof(WCHAR));
    00055             if (pstr->strCapture.Buffer == NULL)
    00056                 return FALSE;
    00057             pstr->fAllocated = TRUE;
    00058             pstr->pstr = &pstr->strCapture;
    00059             pstr->strCapture.MaximumLength = (USHORT)(cbSrc * sizeof(WCHAR));
    00060         } else {
    00061             pstr->pstr = &NtCurrentTeb()->StaticUnicodeString;
    00062         }
    00063
    00064         /*
    00065          * Convert the string to Unicode
    00066          */
    00067         if (RtlMultiByteToUnicodeN(pstr->pstr->Buffer,
    00068                 (ULONG)pstr->pstr->MaximumLength, &cbDst,
    00069                 (LPSTR)psz, cbSrc)) {
    00070             RIPMSG0(RIP_WARNING, "Unicode conversion failed");
    00071             if (pstr->fAllocated) {
    00072                 RtlFreeHeap(pUserHeap, 0, pstr->strCapture.Buffer);
    00073                 pstr->fAllocated = FALSE;
    00074             }
    00075             return FALSE;
    00076         }
    00077         pstr->pstr->Length = (USHORT)cbDst - sizeof(WCHAR);
    00078     } else {
    00079         pstr->pstr = &pstr->strCapture;
    00080         pstr->strCapture.Length = pstr->strCapture.MaximumLength = 0;
    00081         pstr->strCapture.Buffer = NULL;
    00082     }
    00083     return TRUE;
    00084 }
    00085
    00086 /**************************************************************************\
    00087 * RtlCaptureLargeAnsiString
    00088 *
    00089 * Captures a large ANSI string in the same manner as
    00090 * RtlCaptureAnsiString.
    00091 *
    00092 * 03-22-95 JimA         Created.
    00093 \**************************************************************************/
    00094
    00095 BOOL RtlCaptureLargeAnsiString(
    00096     PLARGE_IN_STRING plstr,
    00097     LPCSTR psz,
    00098     BOOL fForceAlloc)
    00099 {
    00100     int cchSrc;
    00101     UINT uLength;
    00102
    00103     plstr->fAllocated = FALSE;
    00104     plstr->pstr = &plstr->strCapture;
    00105
    00106     if (psz) {
    00107         cchSrc = strlen(psz) + 1;
    00108
    00109         /*
    00110          * If the allocation is forced or if the string is
    00111          * too long to fit in the TEB, allocate a buffer.
    00112          * Otherwise, store the result in the TEB.
    00113          */
    00114         if (fForceAlloc || cchSrc > STATIC_UNICODE_BUFFER_LENGTH) {
    00115             plstr->strCapture.Buffer = RtlAllocateHeap(pUserHeap,
    00116                     0, cchSrc * sizeof(WCHAR));
    00117             if (plstr->strCapture.Buffer == NULL)
    00118                 return FALSE;
    00119             plstr->fAllocated = TRUE;
    00120             plstr->strCapture.MaximumLength = cchSrc * sizeof(WCHAR);
    00121         } else {
    00122             plstr->strCapture.Buffer = NtCurrentTeb()->StaticUnicodeBuffer;
    00123             plstr->strCapture.MaximumLength =
    00124                     (UINT)(STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR));
    00125         }
    00126
    00127         /*
    00128          * Convert the string to Unicode
    00129          */
    00130         if (RtlMultiByteToUnicodeN(plstr->pstr->Buffer,
    00131                 plstr->pstr->MaximumLength, &uLength,
    00132                 (LPSTR)psz, cchSrc)) {
    00133             RIPMSG0(RIP_WARNING, "Unicode conversion failed");
    00134             if (plstr->fAllocated) {
    00135                 RtlFreeHeap(pUserHeap, 0, plstr->strCapture.Buffer);
    00136                 plstr->fAllocated = FALSE;
    00137             }
    00138             return FALSE;
    00139         }
    00140         plstr->pstr->Length = uLength - sizeof(WCHAR);
    00141     } else {
    00142         plstr->strCapture.Length = plstr->strCapture.MaximumLength = 0;
    00143         plstr->strCapture.Buffer = NULL;
    00144     }
    00145     return TRUE;
    00146 }
    00147
    00148 //++
    00149 //
    00150 // PVOID
    00151 // AllocateFromZone(
    00152 //     IN PZONE_HEADER Zone
    00153 //     )
    00154 //
    00155 // Routine Description:
    00156 //
    00157 //     This routine removes an entry from the zone and returns a pointer to it.
    00158 //
    00159 // Arguments:
    00160 //
    00161 //     Zone - Pointer to the zone header controlling the storage from which the
    00162 //         entry is to be allocated.
    00163 //
    00164 // Return Value:
    00165 //
    00166 //     The function value is a pointer to the storage allocated from the zone.
    00167 //
    00168 /***************************************************************************\
    00169 \***************************************************************************/
    00170
    00171 #define AllocateFromZone(Zone) \
    00172     (PVOID)((Zone)->FreeList.Next); \
    00173     if ( (Zone)->FreeList.Next ) (Zone)->FreeList.Next = (Zone)->FreeList.Next->Next
    00174
    00175
    00176 //++
    00177 //
    00178 // PVOID
    00179 // FreeToZone(
    00180 //     IN PZONE_HEADER Zone,
    00181 //     IN PVOID Block
    00182 //     )
    00183 //
    00184 // Routine Description:
    00185 //
    00186 //     This routine places the specified block of storage back onto the free
    00187 //     list in the specified zone.
    00188 //
    00189 // Arguments:
    00190 //
    00191 //     Zone - Pointer to the zone header controlling the storage to which the
    00192 //         entry is to be inserted.
    00193 //
    00194 //     Block - Pointer to the block of storage to be freed back to the zone.
    00195 //
    00196 // Return Value:
    00197 //
    00198 //     Pointer to previous block of storage that was at the head of the free
    00199 //         list.  NULL implies the zone went from no available free blocks to
    00200 //         at least one free block.
    00201 //
    00202 /***************************************************************************\
    00203 \***************************************************************************/
    00204
    00205 #define FreeToZone(Zone,Block)                                    \
    00206     ( ((PSINGLE_LIST_ENTRY)(Block))->Next = (Zone)->FreeList.Next,  \
    00207       (Zone)->FreeList.Next = ((PSINGLE_LIST_ENTRY)(Block)),        \
    00208       ((PSINGLE_LIST_ENTRY)(Block))->Next                           \
    00209     )
    00210
    00211 /***************************************************************************\
    00212 * InitLookaside
    00213 *
    00214 * Initializes the lookaside list. This improves control locality
    00215 * by keeping control entries in a single page
    00216 *
    00217 * 05-04-95 JimA         Created.
    00218 \***************************************************************************/
    00219
    00220 NTSTATUS
    00221 InitLookaside(
    00222     PLOOKASIDE pla,
    00223     DWORD cbEntry,
    00224     DWORD cEntries)
    00225 {
    00226     ULONG i;
    00227     PCH p;
    00228     ULONG BlockSize;
    00229     PZONE_HEADER Zone;
    00230     PVOID InitialSegment;
    00231     ULONG InitialSegmentSize;
    00232
    00233     InitialSegmentSize = (cEntries * cbEntry) + sizeof(ZONE_SEGMENT_HEADER);
    00234
    00235     p = (PCH)UserLocalAlloc(0, InitialSegmentSize);
    00236
    00237     if ( !p ) {
    00238         return STATUS_NO_MEMORY;
    00239         }
    00240
    00241     RtlEnterCriticalSection(&gcsLookaside);
    00242
    00243     //
    00244     // If the lookaside list has already been initialized, we're done.
    00245     //
    00246
    00247     if (pla->LookasideBase != NULL && pla->EntrySize == cbEntry) {
    00248         RtlLeaveCriticalSection(&gcsLookaside);
    00249         UserLocalFree(p);
    00250         return STATUS_SUCCESS;
    00251     }
    00252
    00253     pla->LookasideBase = (PVOID)p;
    00254     pla->LookasideBounds = (PVOID)(p + InitialSegmentSize);
    00255     pla->EntrySize = cbEntry;
    00256
    00257     //
    00258     // Using the ExZone-like code, slice up the page into QMSG's
    00259     //
    00260
    00261     Zone = &pla->LookasideZone;
    00262     BlockSize = cbEntry;
    00263     InitialSegment = pla->LookasideBase;
    00264
    00265     Zone->BlockSize = BlockSize;
    00266
    00267     Zone->SegmentList.Next = &((PZONE_SEGMENT_HEADER) InitialSegment)->SegmentList;
    00268     ((PZONE_SEGMENT_HEADER) InitialSegment)->SegmentList.Next = NULL;
    00269     ((PZONE_SEGMENT_HEADER) InitialSegment)->Reserved = NULL;
    00270
    00271     Zone->FreeList.Next = NULL;
    00272
    00273     p = (PCH)InitialSegment + sizeof(ZONE_SEGMENT_HEADER);
    00274
    00275     for (i = sizeof(ZONE_SEGMENT_HEADER);
    00276          i <= InitialSegmentSize - BlockSize;
    00277          i += BlockSize
    00278         ) {
    00279         ((PSINGLE_LIST_ENTRY)p)->Next = Zone->FreeList.Next;
    00280         Zone->FreeList.Next = (PSINGLE_LIST_ENTRY)p;
    00281         p += BlockSize;
    00282     }
    00283     Zone->TotalSegmentSize = i;
    00284
    00285     RtlLeaveCriticalSection(&gcsLookaside);
    00286
    00287     return STATUS_SUCCESS;
    00288
    00289 }
    00290
    00291 /***************************************************************************\
    00292 * AllocLookasideEntry
    00293 *
    00294 * Allocates an entry from the lookaside list.
    00295 *
    00296 * 05-04-95 JimA         Created.
    00297 \***************************************************************************/
    00298
    00299 PVOID AllocLookasideEntry(
    00300     PLOOKASIDE pla)
    00301 {
    00302     PVOID pEntry;
    00303
    00304     //
    00305     // Attempt to get an entry from the zone. If this fails, then
    00306     // LocalAlloc the entry
    00307     //
    00308
    00309     RtlEnterCriticalSection(&gcsLookaside);
    00310     pEntry = AllocateFromZone(&pla->LookasideZone);
    00311     RtlLeaveCriticalSection(&gcsLookaside);
    00312
    00313     if ( !pEntry ) {
    00314
    00315         /*
    00316          * Allocate a local structure.
    00317          */
    00318 #if DBG
    00319         pla->AllocSlowCalls++;
    00320 #endif // DBG
    00321         if ((pEntry = UserLocalAlloc(0, pla->EntrySize)) == NULL)
    00322             return NULL;
    00323         }
    00324     RtlZeroMemory(pEntry, pla->EntrySize);
    00325 #if DBG
    00326     pla->AllocCalls++;
    00327
    00328     if (pla->AllocCalls - pla->DelCalls > pla->AllocHiWater ) {
    00329         pla->AllocHiWater = pla->AllocCalls - pla->DelCalls;
    00330         }
    00331 #endif // DBG
    00332
    00333     return pEntry;
    00334 }
    00335
    00336 /***************************************************************************\
    00337 * FreeLookasideEntry
    00338 *
    00339 * Returns a qmsg to the lookaside buffer or free the memory.
    00340 *
    00341 * 05-04-95 JimA         Created.
    00342 \***************************************************************************/
    00343
    00344 void FreeLookasideEntry(
    00345     PLOOKASIDE pla,
    00346     PVOID pEntry)
    00347 {
    00348 #if DBG
    00349     pla->DelCalls++;
    00350 #endif // DBG
    00351
    00352     //
    00353     // If the pEntry was from zone, then free to zone
    00354     //
    00355     if ( (PVOID)pEntry >= pla->LookasideBase && (PVOID)pEntry < pla->LookasideBounds ) {
    00356         RtlEnterCriticalSection(&gcsLookaside);
    00357         FreeToZone(&pla->LookasideZone,pEntry);
    00358         RtlLeaveCriticalSection(&gcsLookaside);
    00359     } else {
    00360 #if DBG
    00361         pla->DelSlowCalls++;
    00362 #endif // DBG
    00363         UserLocalFree(pEntry);
    00364     }
    00365 }
    00366
    00367