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

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