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

hivechek.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1991 Microsoft Corporation 00004 00005 Module Name: 00006 00007 hivechek.c 00008 00009 Abstract: 00010 00011 This module implements consistency checking for hives. 00012 00013 Author: 00014 00015 Bryan M. Willman (bryanwi) 09-Dec-91 00016 00017 Environment: 00018 00019 00020 Revision History: 00021 00022 --*/ 00023 00024 #include "cmp.h" 00025 00026 #ifdef ALLOC_PRAGMA 00027 #pragma alloc_text(PAGE,HvCheckHive) 00028 #pragma alloc_text(PAGE,HvCheckBin) 00029 #endif 00030 00031 // 00032 // debug structures 00033 // 00034 extern struct { 00035 PHHIVE Hive; 00036 ULONG Status; 00037 ULONG Space; 00038 HCELL_INDEX MapPoint; 00039 PHBIN BinPoint; 00040 } HvCheckHiveDebug; 00041 00042 extern struct { 00043 PHBIN Bin; 00044 ULONG Status; 00045 PHCELL CellPoint; 00046 } HvCheckBinDebug; 00047 00048 00049 #if DBG 00050 ULONG HvHiveChecking=0; 00051 #endif 00052 00053 ULONG 00054 HvCheckHive( 00055 PHHIVE Hive, 00056 PULONG Storage OPTIONAL 00057 ) 00058 /*++ 00059 00060 Routine Description: 00061 00062 Check the consistency of a hive. Apply CheckBin to bins, make sure 00063 all pointers in the cell map point to correct places. 00064 00065 Arguments: 00066 00067 Hive - supplies a pointer to the hive control structure for the 00068 hive of interest. 00069 00070 Storage - supplies adddress of ULONG to receive size of allocated user data 00071 00072 Return Value: 00073 00074 0 if Hive is OK. Error return indicator if not. Error value 00075 comes from one of the check procedures. 00076 00077 RANGE: 2000 - 2999 00078 00079 --*/ 00080 { 00081 HCELL_INDEX p; 00082 ULONG Length; 00083 ULONG localstorage = 0; 00084 PHMAP_ENTRY t; 00085 PHBIN Bin; 00086 ULONG i; 00087 ULONG rc; 00088 PFREE_HBIN FreeBin; 00089 00090 HvCheckHiveDebug.Hive = Hive; 00091 HvCheckHiveDebug.Status = 0; 00092 HvCheckHiveDebug.Space = (ULONG)-1; 00093 HvCheckHiveDebug.MapPoint = HCELL_NIL; 00094 HvCheckHiveDebug.BinPoint = 0; 00095 00096 p = 0; 00097 00098 00099 // 00100 // one pass for Stable space, one pass for Volatile 00101 // 00102 for (i = 0; i <= Volatile; i++) { 00103 Length = Hive->Storage[i].Length; 00104 00105 // 00106 // for each bin in the space 00107 // 00108 while (p < Length) { 00109 t = HvpGetCellMap(Hive, p); 00110 if (t == NULL) { 00111 KdPrint(("HvCheckHive:")); 00112 KdPrint(("\tBin@:%08lx invalid\n", Bin)); 00113 HvCheckHiveDebug.Status = 2005; 00114 HvCheckHiveDebug.Space = i; 00115 HvCheckHiveDebug.MapPoint = p; 00116 return 2005; 00117 } 00118 00119 00120 if ((t->BinAddress & HMAP_DISCARDABLE) == 0) { 00121 00122 Bin = (PHBIN)((t->BinAddress) & HMAP_BASE); 00123 00124 // 00125 // bin header valid? 00126 // 00127 if ( (Bin->Size > Length) || 00128 (Bin->Signature != HBIN_SIGNATURE) || 00129 (Bin->FileOffset != p) 00130 ) 00131 { 00132 KdPrint(("HvCheckHive:")); 00133 KdPrint(("\tBin@:%08lx invalid\n", Bin)); 00134 HvCheckHiveDebug.Status = 2010; 00135 HvCheckHiveDebug.Space = i; 00136 HvCheckHiveDebug.MapPoint = p; 00137 HvCheckHiveDebug.BinPoint = Bin; 00138 return 2010; 00139 } 00140 00141 // 00142 // structure inside the bin valid? 00143 // 00144 rc = HvCheckBin(Hive, Bin, &localstorage); 00145 if (rc != 0) { 00146 HvCheckHiveDebug.Status = rc; 00147 HvCheckHiveDebug.Space = i; 00148 HvCheckHiveDebug.MapPoint = p; 00149 HvCheckHiveDebug.BinPoint = Bin; 00150 return rc; 00151 } 00152 00153 p = (ULONG)p + Bin->Size; 00154 00155 } else { 00156 // 00157 // Bin is not present, skip it and advance to the next one. 00158 // 00159 FreeBin = (PFREE_HBIN)t->BlockAddress; 00160 p+=FreeBin->Size; 00161 } 00162 } 00163 00164 p = 0x80000000; // Beginning of Volatile space 00165 } 00166 00167 if (ARGUMENT_PRESENT(Storage)) { 00168 *Storage = localstorage; 00169 } 00170 return 0; 00171 } 00172 00173 00174 ULONG 00175 HvCheckBin( 00176 PHHIVE Hive, 00177 PHBIN Bin, 00178 PULONG Storage 00179 ) 00180 /*++ 00181 00182 Routine Description: 00183 00184 Step through all of the cells in the bin. Make sure that 00185 they are consistent with each other, and with the bin header. 00186 00187 Arguments: 00188 00189 Hive - pointer to the hive control structure 00190 00191 Bin - pointer to bin to check 00192 00193 Storage - pointer to a ulong to get allocated user data size 00194 00195 Return Value: 00196 00197 0 if Bin is OK. Number of test in procedure that failed if not. 00198 00199 RANGE: 1 - 1999 00200 00201 --*/ 00202 { 00203 PHCELL p; 00204 PHCELL np; 00205 PHCELL lp; 00206 ULONG freespace = 0L; 00207 ULONG allocated = 0L; 00208 ULONG userallocated = 0L; 00209 00210 HvCheckBinDebug.Bin = Bin; 00211 HvCheckBinDebug.Status = 0; 00212 HvCheckBinDebug.CellPoint = 0; 00213 00214 // 00215 // Scan all the cells in the bin, total free and allocated, check 00216 // for impossible pointers. 00217 // 00218 p = (PHCELL)((PUCHAR)Bin + sizeof(HBIN)); 00219 lp = p; 00220 00221 // DRAGOS: 00222 // The way allocated and freespace are computed implies the following invariants: 00223 // 1. allocated + freespace = p + p->Size - (Bin + sizeof(HBIN)). This is because p->Size is added either to allocated or to freespace. 00224 // So, assuming that allocated > Bin->Size , then 00225 // ==> p + p->Size - (Bin + sizeof(HBIN)) > Bin->Size. 00226 // ==> p + p->Size > Bin + Bin->Size + sizeof(HBIN) 00227 // ==> p + p->Size > Bin + Bin->Size 00228 // This proves that the test "NeverFail 1" (see bellow) will never fail, because when something is wrong, the test above it (namely "Fail 1") will fail 00229 // and the function will exit. 00230 // 00231 // The same logic applies to the test "NeverFail 2", so it can be removed also. 00232 // 00233 // 2. The new value of p is always calculated as p = p + p->Size. By the time this is done, the new value of p (ie. p + p->Size) is already checked against 00234 // Bin + Bin->Size (see tests "Fail 1" and "Fail 2"). So, if p > Bin + Bin->Size, either "Fail 1" or "Fail 2" will fail before asigning the new bogus value 00235 // to p. Therefore, the only possible path to exit the while loop (except a return 20 or return 40), is when p == Bin + Bin->Size. 00236 // ==> test "NeverFail 3" can be removed as it will never fail ! 00237 // 00238 // 3. Considering 1 (where p + p->Size became p) 00239 // ==> allocated + freespace = p - (Bin + sizeof(HBIN)) 00240 // But, Considering 2 (above), when the while loop exits, p = Bin + Bin->Size 00241 // ==> allocated + freespace = Bin + Bin->Size - (Bin + sizeof(HBIN)) 00242 // ==> allocated + freespace + sizeof(HBIN) = Bin->Size 00243 // This proves that test "NeverFail 4" (see bellow) will never fail as the expresion tested is always true (if the flow of execution reaches the test point). 00244 // 00245 00246 while (p < (PHCELL)((PUCHAR)Bin + Bin->Size)) { 00247 00248 // 00249 // Check last pointer 00250 // 00251 if (USE_OLD_CELL(Hive)) { 00252 if (lp == p) { 00253 if (p->u.OldCell.Last != HBIN_NIL) { 00254 KdPrint(("HvCheckBin 20: First cell has wrong last pointer\n")); 00255 KdPrint(("Bin = %08lx\n", Bin)); 00256 HvCheckBinDebug.Status = 20; 00257 HvCheckBinDebug.CellPoint = p; 00258 return 20; 00259 } 00260 } else { 00261 if ((PHCELL)(p->u.OldCell.Last + (PUCHAR)Bin) != lp) { 00262 KdPrint(("HvCheckBin 30: incorrect last pointer\n")); 00263 KdPrint(("Bin = %08lx\n", Bin)); 00264 KdPrint(("p = %08lx\n", (ULONG_PTR)p)); 00265 HvCheckBinDebug.Status = 30; 00266 HvCheckBinDebug.CellPoint = p; 00267 return 30; 00268 } 00269 } 00270 } 00271 00272 00273 // 00274 // Check size 00275 // 00276 if (p->Size < 0) { 00277 00278 // 00279 // allocated cell 00280 // 00281 00282 // DRAGOS: Fail 1 00283 // This test will alway fail prior to the failure of the bellow test 00284 // 00285 if ( ((ULONG)(p->Size * -1) > Bin->Size) || 00286 ( (PHCELL)((p->Size * -1) + (PUCHAR)p) > 00287 (PHCELL)((PUCHAR)Bin + Bin->Size) ) 00288 ) 00289 { 00290 KdPrint(("HvCheckBin 40: impossible allocation\n")); 00291 KdPrint(("Bin = %08lx\n", Bin)); 00292 HvCheckBinDebug.Status = 40; 00293 HvCheckBinDebug.CellPoint = p; 00294 return 40; 00295 } 00296 00297 allocated += (p->Size * -1); 00298 if (USE_OLD_CELL(Hive)) { 00299 userallocated += (p->Size * -1) - FIELD_OFFSET(HCELL, u.OldCell.u.UserData); 00300 } else { 00301 userallocated += (p->Size * -1) - FIELD_OFFSET(HCELL, u.NewCell.u.UserData); 00302 } 00303 00304 // 00305 // DRAGOS: NeverFail 1 00306 // This test will never fail. If a size is wrong the above test (Fail 1)will fail. We can remove this test (it's useless). 00307 // 00308 if (allocated > Bin->Size) { 00309 KdPrint(("HvCheckBin 50: allocated exceeds available\n")); 00310 KdPrint(("Bin = %08lx\n", Bin)); 00311 HvCheckBinDebug.Status = 50; 00312 HvCheckBinDebug.CellPoint = p; 00313 return 50; 00314 } 00315 00316 np = (PHCELL)((PUCHAR)p + (p->Size * -1)); 00317 00318 00319 00320 } else { 00321 00322 // 00323 // free cell 00324 // 00325 00326 // DRAGOS: Fail 2 00327 // This test will alway fail prior to the failure of the bellow test 00328 // 00329 if ( ((ULONG)p->Size > Bin->Size) || 00330 ( (PHCELL)(p->Size + (PUCHAR)p) > 00331 (PHCELL)((PUCHAR)Bin + Bin->Size) ) || 00332 (p->Size == 0) ) 00333 { 00334 KdPrint(("HvCheckBin 60: impossible free block\n")); 00335 KdPrint(("Bin = %08lx\n", Bin)); 00336 HvCheckBinDebug.Status = 60; 00337 HvCheckBinDebug.CellPoint = p; 00338 return 60; 00339 } 00340 00341 freespace = freespace + p->Size; 00342 00343 // 00344 // DRAGOS: NeverFail 2 00345 // This test will never fail. If a size is wrong the above test (Fail 2) will fail. We can remove this test (it's useless). 00346 // 00347 if (freespace > Bin->Size) { 00348 KdPrint(("HvCheckBin 70: free exceeds available\n")); 00349 KdPrint(("Bin = %08lx\n", Bin)); 00350 HvCheckBinDebug.Status = 70; 00351 HvCheckBinDebug.CellPoint = p; 00352 return 70; 00353 } 00354 00355 np = (PHCELL)((PUCHAR)p + p->Size); 00356 00357 } 00358 00359 lp = p; 00360 p = np; 00361 } 00362 00363 // DRAGOS: NeverFail 4 00364 // This test never fails. If the while loop exits, the condition tested here is always true!!! 00365 // We can remove this test (it's useless) 00366 // 00367 if ((freespace + allocated + sizeof(HBIN)) != Bin->Size) { 00368 KdPrint(("HvCheckBin 995: sizes do not add up\n")); 00369 KdPrint(("Bin = %08lx\n", Bin)); 00370 KdPrint(("freespace = %08lx ", freespace)); 00371 KdPrint(("allocated = %08lx ", allocated)); 00372 KdPrint(("size = %08lx\n", Bin->Size)); 00373 HvCheckBinDebug.Status = 995; 00374 return 995; 00375 } 00376 00377 // DRAGOS: NeverFail 3 00378 // This test never fails. The only way out of the while loop is when p == Bin + Bin->Size !!!!!!! 00379 // We can remove this test (it's useless) 00380 // 00381 if (p != (PHCELL)((PUCHAR)Bin + Bin->Size)) { 00382 KdPrint(("HvCheckBin 1000: last cell points off the end\n")); 00383 KdPrint(("Bin = %08lx\n", Bin)); 00384 HvCheckBinDebug.Status = 1000; 00385 return 1000; 00386 } 00387 00388 if (ARGUMENT_PRESENT(Storage)) { 00389 *Storage += userallocated; 00390 } 00391 return 0; 00392 }

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