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

udfdata.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 UdfData.c 00008 00009 Abstract: 00010 00011 This module declares the global data used by the Udfs file system. 00012 00013 This module also handles the dispath routines in the Fsd threads as well as 00014 handling the IrpContext and Irp through the exception path. 00015 00016 Author: 00017 00018 Dan Lovinger [DanLo] 24-May-1996 00019 00020 Revision History: 00021 00022 --*/ 00023 00024 #include "UdfProcs.h" 00025 00026 // 00027 // The Bug check file id for this module 00028 // 00029 00030 #define BugCheckFileId (UDFS_BUG_CHECK_UDFDATA) 00031 00032 // 00033 // The local debug trace level 00034 // 00035 00036 #define Dbg (UDFS_DEBUG_LEVEL_UDFDATA) 00037 00038 // 00039 // Global data structures 00040 // 00041 00042 UDF_DATA UdfData; 00043 FAST_IO_DISPATCH UdfFastIoDispatch; 00044 00045 // 00046 // Debug trace levels 00047 // 00048 00049 #ifdef UDF_SANITY 00050 00051 // 00052 // For UdfDebugTrace (only live in checked builds) to be able to swing 00053 // variable argument lists and varargs printfs. 00054 // 00055 00056 #include <stdarg.h> 00057 #include <stdio.h> 00058 00059 BOOLEAN UdfTestTopLevel = TRUE; 00060 BOOLEAN UdfTestRaisedStatus = TRUE; 00061 00062 LONG UdfDebugTraceLevel = 0; 00063 LONG UdfDebugTraceIndent = 0; 00064 00065 // 00066 // Control whether UdfVerifyDescriptor will only emit info on failure (FALSE) or 00067 // all of the time (TRUE). 00068 // 00069 00070 BOOLEAN UdfNoisyVerifyDescriptor = FALSE; 00071 00072 #endif 00073 00074 // 00075 // Reserved directory strings. 00076 // 00077 00078 WCHAR UdfUnicodeSelfArray[] = { L'.' }; 00079 WCHAR UdfUnicodeParentArray[] = { L'.', L'.' }; 00080 00081 UNICODE_STRING UdfUnicodeDirectoryNames[] = { 00082 { sizeof(UdfUnicodeSelfArray), sizeof(UdfUnicodeSelfArray), UdfUnicodeSelfArray}, 00083 { sizeof(UdfUnicodeParentArray), sizeof(UdfUnicodeParentArray), UdfUnicodeParentArray} 00084 }; 00085 00086 // 00087 // Identifier strings defined by UDF. 00088 // 00089 00090 CHAR UdfCS0IdentifierArray[] = { 'O', 'S', 'T', 'A', ' ', 00091 'C', 'o', 'm', 'p', 'r', 'e', 's', 's', 'e', 'd', ' ', 00092 'U', 'n', 'i', 'c', 'o', 'd', 'e' }; 00093 00094 STRING UdfCS0Identifier = { 00095 sizeof(UdfCS0IdentifierArray), 00096 sizeof(UdfCS0IdentifierArray), 00097 UdfCS0IdentifierArray 00098 }; 00099 00100 CHAR UdfDomainIdentifierArray[] = { '*', 'O', 'S', 'T', 'A', ' ', 00101 'U', 'D', 'F', ' ', 00102 'C', 'o', 'm', 'p', 'l', 'i', 'a', 'n', 't' }; 00103 00104 STRING UdfDomainIdentifier = { 00105 sizeof(UdfDomainIdentifierArray), 00106 sizeof(UdfDomainIdentifierArray), 00107 UdfDomainIdentifierArray 00108 }; 00109 00110 CHAR UdfVirtualPartitionDomainIdentifierArray[] = { '*', 'U', 'D', 'F', ' ', 00111 'V', 'i', 'r', 't', 'u', 'a', 'l', ' ', 00112 'P', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n' }; 00113 00114 STRING UdfVirtualPartitionDomainIdentifier = { 00115 sizeof(UdfVirtualPartitionDomainIdentifierArray), 00116 sizeof(UdfVirtualPartitionDomainIdentifierArray), 00117 UdfVirtualPartitionDomainIdentifierArray 00118 }; 00119 00120 CHAR UdfVatTableIdentifierArray[] = { '*', 'U', 'D', 'F', ' ', 00121 'V', 'i', 'r', 't', 'u', 'a', 'l', ' ', 00122 'A', 'l', 'l', 'o', 'c', ' ', 00123 'T', 'b', 'l' }; 00124 00125 STRING UdfVatTableIdentifier = { 00126 sizeof(UdfVatTableIdentifierArray), 00127 sizeof(UdfVatTableIdentifierArray), 00128 UdfVatTableIdentifierArray 00129 }; 00130 00131 CHAR UdfSparablePartitionDomainIdentifierArray[] = { '*', 'U', 'D', 'F', ' ', 00132 'S', 'p', 'a', 'r', 'a', 'b', 'l', 'e', ' ', 00133 'P', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n' }; 00134 00135 STRING UdfSparablePartitionDomainIdentifier = { 00136 sizeof(UdfSparablePartitionDomainIdentifierArray), 00137 sizeof(UdfSparablePartitionDomainIdentifierArray), 00138 UdfSparablePartitionDomainIdentifierArray 00139 }; 00140 00141 CHAR UdfSparingTableIdentifierArray[] = { '*', 'U', 'D', 'F', ' ', 00142 'S', 'p', 'a', 'r', 'i', 'n', 'g', ' ', 00143 'T', 'a', 'b', 'l', 'e' }; 00144 00145 STRING UdfSparingTableIdentifier = { 00146 sizeof(UdfSparingTableIdentifierArray), 00147 sizeof(UdfSparingTableIdentifierArray), 00148 UdfSparingTableIdentifierArray 00149 }; 00150 00151 CHAR UdfNSR02IdentifierArray[] = NSR_PART_CONTID_NSR02; 00152 00153 STRING UdfNSR02Identifier = { 00154 sizeof(UdfNSR02IdentifierArray), 00155 sizeof(UdfNSR02IdentifierArray), 00156 UdfNSR02IdentifierArray 00157 }; 00158 00159 // 00160 // Tables of tokens we have to parse up from mount-time on-disk structures 00161 // 00162 00163 PARSE_KEYVALUE VsdIdentParseTable[] = { 00164 { VSD_IDENT_BEA01, VsdIdentBEA01 }, 00165 { VSD_IDENT_TEA01, VsdIdentTEA01 }, 00166 { VSD_IDENT_CDROM, VsdIdentCDROM }, 00167 { VSD_IDENT_CD001, VsdIdentCD001 }, 00168 { VSD_IDENT_CDW01, VsdIdentCDW01 }, 00169 { VSD_IDENT_CDW02, VsdIdentCDW02 }, 00170 { VSD_IDENT_NSR01, VsdIdentNSR01 }, 00171 { VSD_IDENT_NSR02, VsdIdentNSR02 }, 00172 { VSD_IDENT_BOOT2, VsdIdentBOOT2 }, 00173 { NULL, VsdIdentBad } 00174 }; 00175 00176 PARSE_KEYVALUE NsrPartContIdParseTable[] = { 00177 { NSR_PART_CONTID_FDC01, NsrPartContIdFDC01 }, 00178 { NSR_PART_CONTID_CD001, NsrPartContIdCD001 }, 00179 { NSR_PART_CONTID_CDW01, NsrPartContIdCDW01 }, 00180 { NSR_PART_CONTID_CDW02, NsrPartContIdCDW02 }, 00181 { NSR_PART_CONTID_NSR01, NsrPartContIdNSR01 }, 00182 { NSR_PART_CONTID_NSR02, NsrPartContIdNSR02 }, 00183 { NULL, NsrPartContIdBad } 00184 }; 00185 00186 // 00187 // Lookaside allocation lists for various volatile structures 00188 // 00189 00190 NPAGED_LOOKASIDE_LIST UdfFcbNonPagedLookasideList; 00191 NPAGED_LOOKASIDE_LIST UdfIrpContextLookasideList; 00192 00193 PAGED_LOOKASIDE_LIST UdfCcbLookasideList; 00194 PAGED_LOOKASIDE_LIST UdfFcbIndexLookasideList; 00195 PAGED_LOOKASIDE_LIST UdfFcbDataLookasideList; 00196 PAGED_LOOKASIDE_LIST UdfLcbLookasideList; 00197 00198 // 00199 // 16bit CRC table 00200 // 00201 00202 PUSHORT UdfCrcTable; 00203 00204 #ifdef ALLOC_PRAGMA 00205 #pragma alloc_text(PAGE, UdfComputeCrc16) 00206 #pragma alloc_text(PAGE, UdfComputeCrc16Uni) 00207 #ifdef UDF_SANITY 00208 #pragma alloc_text(PAGE, UdfDebugTrace) 00209 #endif 00210 #pragma alloc_text(PAGE, UdfFastIoCheckIfPossible) 00211 #pragma alloc_text(PAGE, UdfHighBit) 00212 #pragma alloc_text(PAGE, UdfInitializeCrc16) 00213 #pragma alloc_text(PAGE, UdfSerial32) 00214 #endif 00215 00216 00217 NTSTATUS 00218 UdfFsdDispatch ( 00219 IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, 00220 IN PIRP Irp 00221 ) 00222 00223 /*++ 00224 00225 Routine Description: 00226 00227 This is the driver entry to all of the Fsd dispatch points. 00228 00229 Conceptually the Io routine will call this routine on all requests 00230 to the file system. We case on the type of request and invoke the 00231 correct handler for this type of request. There is an exception filter 00232 to catch any exceptions in the UDFS code as well as the UDFS process 00233 exception routine. 00234 00235 This routine allocates and initializes the IrpContext for this request as 00236 well as updating the top-level thread context as necessary. We may loop 00237 in this routine if we need to retry the request for any reason. The 00238 status code STATUS_CANT_WAIT is used to indicate this. Suppose the disk 00239 in the drive has changed. An Fsd request will proceed normally until it 00240 recognizes this condition. STATUS_VERIFY_REQUIRED is raised at that point 00241 and the exception code will handle the verify and either return 00242 STATUS_CANT_WAIT or STATUS_PENDING depending on whether the request was 00243 posted. 00244 00245 Arguments: 00246 00247 VolumeDeviceObject - Supplies the volume device object for this request 00248 00249 Irp - Supplies the Irp being processed 00250 00251 Return Value: 00252 00253 NTSTATUS - The FSD status for the IRP 00254 00255 --*/ 00256 00257 { 00258 THREAD_CONTEXT ThreadContext; 00259 PIRP_CONTEXT IrpContext = NULL; 00260 BOOLEAN Wait; 00261 00262 #ifdef UDF_SANITY 00263 PVOID PreviousTopLevel; 00264 #endif 00265 00266 NTSTATUS Status; 00267 00268 KIRQL SaveIrql = KeGetCurrentIrql(); 00269 00270 ASSERT_OPTIONAL_IRP( Irp ); 00271 00272 FsRtlEnterFileSystem(); 00273 00274 #ifdef UDF_SANITY 00275 PreviousTopLevel = IoGetTopLevelIrp(); 00276 #endif 00277 00278 // 00279 // Loop until this request has been completed or posted. 00280 // 00281 00282 do { 00283 00284 // 00285 // Use a try-except to handle the exception cases. 00286 // 00287 00288 try { 00289 00290 // 00291 // If the IrpContext is NULL then this is the first pass through 00292 // this loop. 00293 // 00294 00295 if (IrpContext == NULL) { 00296 00297 // 00298 // Decide if this request is waitable an allocate the IrpContext. 00299 // If the file object in the stack location is NULL then this 00300 // is a mount which is always waitable. Otherwise we look at 00301 // the file object flags. 00302 // 00303 00304 if (IoGetCurrentIrpStackLocation( Irp )->FileObject == NULL) { 00305 00306 Wait = TRUE; 00307 00308 } else { 00309 00310 Wait = CanFsdWait( Irp ); 00311 } 00312 00313 IrpContext = UdfCreateIrpContext( Irp, Wait ); 00314 00315 // 00316 // Update the thread context information. 00317 // 00318 00319 UdfSetThreadContext( IrpContext, &ThreadContext ); 00320 00321 #ifdef UDF_SANITY 00322 ASSERT( !UdfTestTopLevel || 00323 SafeNodeType( IrpContext->TopLevel ) == UDFS_NTC_IRP_CONTEXT ); 00324 #endif 00325 00326 // 00327 // Otherwise cleanup the IrpContext for the retry. 00328 // 00329 00330 } else { 00331 00332 // 00333 // Set the MORE_PROCESSING flag to make sure the IrpContext 00334 // isn't inadvertently deleted here. Then cleanup the 00335 // IrpContext to perform the retry. 00336 // 00337 00338 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING ); 00339 UdfCleanupIrpContext( IrpContext, FALSE ); 00340 } 00341 00342 // 00343 // Case on the major irp code. 00344 // 00345 00346 switch (IrpContext->MajorFunction) { 00347 00348 case IRP_MJ_CLEANUP : 00349 00350 Status = UdfCommonCleanup( IrpContext, Irp ); 00351 break; 00352 00353 case IRP_MJ_CLOSE : 00354 00355 Status = UdfCommonClose( IrpContext, Irp ); 00356 break; 00357 00358 case IRP_MJ_CREATE : 00359 00360 Status = UdfCommonCreate( IrpContext, Irp ); 00361 break; 00362 00363 case IRP_MJ_DEVICE_CONTROL : 00364 00365 Status = UdfCommonDevControl( IrpContext, Irp ); 00366 break; 00367 00368 case IRP_MJ_DIRECTORY_CONTROL : 00369 00370 Status = UdfCommonDirControl( IrpContext, Irp ); 00371 break; 00372 00373 case IRP_MJ_FILE_SYSTEM_CONTROL : 00374 00375 Status = UdfCommonFsControl( IrpContext, Irp ); 00376 break; 00377 00378 case IRP_MJ_LOCK_CONTROL : 00379 00380 Status = UdfCommonLockControl( IrpContext, Irp ); 00381 break; 00382 00383 case IRP_MJ_PNP : 00384 00385 Status = UdfCommonPnp( IrpContext, Irp ); 00386 break; 00387 00388 case IRP_MJ_QUERY_INFORMATION : 00389 00390 Status = UdfCommonQueryInfo( IrpContext, Irp ); 00391 break; 00392 00393 case IRP_MJ_QUERY_VOLUME_INFORMATION : 00394 00395 Status = UdfCommonQueryVolInfo( IrpContext, Irp ); 00396 break; 00397 00398 case IRP_MJ_READ : 00399 00400 // 00401 // If this is an Mdl complete request, don't go through 00402 // common read. 00403 // 00404 00405 if (FlagOn( IrpContext->MinorFunction, IRP_MN_COMPLETE )) { 00406 00407 Status = UdfCompleteMdl( IrpContext, Irp ); 00408 00409 } else { 00410 00411 Status = UdfCommonRead( IrpContext, Irp ); 00412 } 00413 00414 break; 00415 00416 case IRP_MJ_SET_INFORMATION : 00417 00418 Status = UdfCommonSetInfo( IrpContext, Irp ); 00419 break; 00420 00421 default : 00422 00423 Status = STATUS_INVALID_DEVICE_REQUEST; 00424 UdfCompleteRequest( IrpContext, Irp, Status ); 00425 } 00426 00427 } except( UdfExceptionFilter( IrpContext, GetExceptionInformation() )) { 00428 00429 Status = UdfProcessException( IrpContext, Irp, GetExceptionCode() ); 00430 } 00431 00432 } while (Status == STATUS_CANT_WAIT); 00433 00434 #ifdef UDF_SANITY 00435 ASSERT( !UdfTestTopLevel || 00436 (PreviousTopLevel == IoGetTopLevelIrp()) ); 00437 #endif 00438 00439 FsRtlExitFileSystem(); 00440 00441 ASSERT( SaveIrql == KeGetCurrentIrql( )); 00442 00443 return Status; 00444 } 00445 00446 00447 LONG 00448 UdfExceptionFilter ( 00449 IN PIRP_CONTEXT IrpContext, 00450 IN PEXCEPTION_POINTERS ExceptionPointer 00451 ) 00452 00453 /*++ 00454 00455 Routine Description: 00456 00457 This routine is used to decide whether we will handle a raised exception 00458 status. If UDFS explicitly raised an error then this status is already 00459 in the IrpContext. We choose which is the correct status code and 00460 either indicate that we will handle the exception or bug-check the system. 00461 00462 Arguments: 00463 00464 ExceptionCode - Supplies the exception code to being checked. 00465 00466 Return Value: 00467 00468 ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks 00469 00470 --*/ 00471 00472 { 00473 NTSTATUS ExceptionCode; 00474 BOOLEAN TestStatus = TRUE; 00475 00476 ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext ); 00477 00478 ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode; 00479 00480 DebugTrace(( 0, Dbg, 00481 "UdfExceptionFilter: %08x (exr %08x cxr %08x)\n", 00482 ExceptionCode, 00483 ExceptionPointer->ExceptionRecord, 00484 ExceptionPointer->ContextRecord )); 00485 00486 00487 // 00488 // If the exception is STATUS_IN_PAGE_ERROR, get the I/O error code 00489 // from the exception record. 00490 // 00491 00492 if ((ExceptionCode == STATUS_IN_PAGE_ERROR) && 00493 (ExceptionPointer->ExceptionRecord->NumberParameters >= 3)) { 00494 00495 ExceptionCode = (NTSTATUS) ExceptionPointer->ExceptionRecord->ExceptionInformation[2]; 00496 } 00497 00498 // 00499 // If there is an Irp context then check which status code to use. 00500 // 00501 00502 if (ARGUMENT_PRESENT( IrpContext )) { 00503 00504 if (IrpContext->ExceptionStatus == STATUS_SUCCESS) { 00505 00506 // 00507 // Store the real status into the IrpContext. 00508 // 00509 00510 IrpContext->ExceptionStatus = ExceptionCode; 00511 00512 } else { 00513 00514 // 00515 // No need to test the status code if we raised it ourselves. 00516 // 00517 00518 TestStatus = FALSE; 00519 } 00520 } 00521 00522 // 00523 // Bug check if this status is not supported. 00524 // 00525 00526 if (TestStatus && !FsRtlIsNtstatusExpected( ExceptionCode )) { 00527 00528 UdfBugCheck( (ULONG_PTR) ExceptionPointer->ExceptionRecord, 00529 (ULONG_PTR) ExceptionPointer->ContextRecord, 00530 (ULONG_PTR) ExceptionPointer->ExceptionRecord->ExceptionAddress ); 00531 00532 } 00533 00534 return EXCEPTION_EXECUTE_HANDLER; 00535 } 00536 00537 00538 NTSTATUS 00539 UdfProcessException ( 00540 IN PIRP_CONTEXT IrpContext OPTIONAL, 00541 IN PIRP Irp, 00542 IN NTSTATUS ExceptionCode 00543 ) 00544 00545 /*++ 00546 00547 Routine Description: 00548 00549 This routine processes an exception. It either completes the request 00550 with the exception status in the IrpContext, sends this off to the Fsp 00551 workque or causes it to be retried in the current thread if a verification 00552 is needed. 00553 00554 If the volume needs to be verified (STATUS_VERIFY_REQUIRED) and we can 00555 do the work in the current thread we will translate the status code 00556 to STATUS_CANT_WAIT to indicate that we need to retry the request. 00557 00558 Arguments: 00559 00560 Irp - Supplies the Irp being processed 00561 00562 ExceptionCode - Supplies the normalized exception status being handled 00563 00564 Return Value: 00565 00566 NTSTATUS - Returns the results of either posting the Irp or the 00567 saved completion status. 00568 00569 --*/ 00570 00571 { 00572 PDEVICE_OBJECT Device; 00573 PVPB Vpb; 00574 PETHREAD Thread; 00575 00576 ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext ); 00577 ASSERT_IRP( Irp ); 00578 00579 // 00580 // If there is not an irp context, then complete the request with the 00581 // current status code. 00582 // 00583 00584 if (!ARGUMENT_PRESENT( IrpContext )) { 00585 00586 UdfCompleteRequest( NULL, Irp, ExceptionCode ); 00587 return ExceptionCode; 00588 } 00589 00590 // 00591 // Get the real exception status from the IrpContext. 00592 // 00593 00594 ExceptionCode = IrpContext->ExceptionStatus; 00595 00596 // 00597 // If we are not a top level request then we just complete the request 00598 // with the current status code. 00599 // 00600 00601 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL )) { 00602 00603 UdfCompleteRequest( IrpContext, Irp, ExceptionCode ); 00604 00605 return ExceptionCode; 00606 } 00607 00608 // 00609 // Check if we are posting this request. One of the following must be true 00610 // if we are to post a request. 00611 // 00612 // - Status code is STATUS_CANT_WAIT and the request is asynchronous 00613 // or we are forcing this to be posted. 00614 // 00615 // - Status code is STATUS_VERIFY_REQUIRED and we are at APC level 00616 // or higher. Can't wait for IO in the verify path in this case. 00617 // 00618 // Set the MORE_PROCESSING flag in the IrpContext to keep if from being 00619 // deleted if this is a retryable condition. 00620 // 00621 // Note: Children of UdfFsdPostRequest() can raise. 00622 // 00623 00624 try { 00625 00626 if (ExceptionCode == STATUS_CANT_WAIT) { 00627 00628 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST )) { 00629 00630 ExceptionCode = UdfFsdPostRequest( IrpContext, Irp ); 00631 } 00632 00633 } else if (ExceptionCode == STATUS_VERIFY_REQUIRED) { 00634 00635 if (KeGetCurrentIrql() >= APC_LEVEL) { 00636 00637 ExceptionCode = UdfFsdPostRequest( IrpContext, Irp ); 00638 } 00639 } 00640 } 00641 except (UdfExceptionFilter( IrpContext, GetExceptionInformation())) { 00642 00643 ExceptionCode = GetExceptionCode(); 00644 } 00645 00646 // 00647 // If we posted the request or our caller will retry then just return here. 00648 // 00649 00650 if ((ExceptionCode == STATUS_PENDING) || 00651 (ExceptionCode == STATUS_CANT_WAIT)) { 00652 00653 return ExceptionCode; 00654 } 00655 00656 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING ); 00657 00658 // 00659 // Store this error into the Irp for posting back to the Io system. 00660 // 00661 00662 Irp->IoStatus.Status = ExceptionCode; 00663 00664 if (IoIsErrorUserInduced( ExceptionCode )) { 00665 00666 // 00667 // Check for the various error conditions that can be caused by, 00668 // and possibly resolved my the user. 00669 // 00670 00671 if (ExceptionCode == STATUS_VERIFY_REQUIRED) { 00672 00673 // 00674 // Now we are at the top level file system entry point. 00675 // 00676 // If we have already posted this request then the device to 00677 // verify is in the original thread. Find this via the Irp. 00678 // 00679 00680 Device = IoGetDeviceToVerify( Irp->Tail.Overlay.Thread ); 00681 IoSetDeviceToVerify( Irp->Tail.Overlay.Thread, NULL ); 00682 00683 // 00684 // If there is no device in that location then check in the 00685 // current thread. 00686 // 00687 00688 if (Device == NULL) { 00689 00690 Device = IoGetDeviceToVerify( PsGetCurrentThread() ); 00691 IoSetDeviceToVerify( PsGetCurrentThread(), NULL ); 00692 00693 ASSERT( Device != NULL ); 00694 00695 // 00696 // Let's not BugCheck just because the driver screwed up. 00697 // 00698 00699 if (Device == NULL) { 00700 00701 ExceptionCode = STATUS_DRIVER_INTERNAL_ERROR; 00702 00703 UdfCompleteRequest( IrpContext, Irp, ExceptionCode ); 00704 00705 return ExceptionCode; 00706 } 00707 } 00708 00709 // 00710 // CdPerformVerify() will do the right thing with the Irp. 00711 // If we return STATUS_CANT_WAIT then the current thread 00712 // can retry the request. 00713 // 00714 00715 return UdfPerformVerify( IrpContext, Irp, Device ); 00716 } 00717 00718 // 00719 // The other user induced conditions generate an error unless 00720 // they have been disabled for this request. 00721 // 00722 00723 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS )) { 00724 00725 UdfCompleteRequest( IrpContext, Irp, ExceptionCode ); 00726 00727 return ExceptionCode; 00728 00729 } else { 00730 00731 // 00732 // Generate a pop-up 00733 // 00734 00735 if (IoGetCurrentIrpStackLocation( Irp )->FileObject != NULL) { 00736 00737 Vpb = IoGetCurrentIrpStackLocation( Irp )->FileObject->Vpb; 00738 00739 } else { 00740 00741 Vpb = NULL; 00742 } 00743 00744 // 00745 // The device to verify is either in my thread local storage 00746 // or that of the thread that owns the Irp. 00747 // 00748 00749 Thread = Irp->Tail.Overlay.Thread; 00750 Device = IoGetDeviceToVerify( Thread ); 00751 00752 if (Device == NULL) { 00753 00754 Thread = PsGetCurrentThread(); 00755 Device = IoGetDeviceToVerify( Thread ); 00756 00757 ASSERT( Device != NULL ); 00758 00759 // 00760 // Let's not BugCheck just because the driver screwed up. 00761 // 00762 00763 if (Device == NULL) { 00764 00765 UdfCompleteRequest( IrpContext, Irp, ExceptionCode ); 00766 00767 return ExceptionCode; 00768 } 00769 } 00770 00771 // 00772 // This routine actually causes the pop-up. It usually 00773 // does this by queuing an APC to the callers thread, 00774 // but in some cases it will complete the request immediately, 00775 // so it is very important to IoMarkIrpPending() first. 00776 // 00777 00778 IoMarkIrpPending( Irp ); 00779 IoRaiseHardError( Irp, Vpb, Device ); 00780 00781 // 00782 // We will be handing control back to the caller here, so 00783 // reset the saved device object. 00784 // 00785 00786 IoSetDeviceToVerify( Thread, NULL ); 00787 00788 // 00789 // The Irp will be completed by Io or resubmitted. In either 00790 // case we must clean up the IrpContext here. 00791 // 00792 00793 UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); 00794 return STATUS_PENDING; 00795 } 00796 } 00797 00798 // 00799 // This is just a run of the mill error. 00800 // 00801 00802 UdfCompleteRequest( IrpContext, Irp, ExceptionCode ); 00803 00804 return ExceptionCode; 00805 } 00806 00807 00808 VOID 00809 UdfCompleteRequest ( 00810 IN PIRP_CONTEXT IrpContext OPTIONAL, 00811 IN PIRP Irp OPTIONAL, 00812 IN NTSTATUS Status 00813 ) 00814 00815 /*++ 00816 00817 Routine Description: 00818 00819 This routine completes a Irp and cleans up the IrpContext. Either or 00820 both of these may not be specified. 00821 00822 Arguments: 00823 00824 Irp - Supplies the Irp being processed. 00825 00826 Status - Supplies the status to complete the Irp with 00827 00828 Return Value: 00829 00830 None. 00831 00832 --*/ 00833 00834 { 00835 ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext ); 00836 ASSERT_OPTIONAL_IRP( Irp ); 00837 00838 // 00839 // Cleanup the IrpContext if passed in here. 00840 // 00841 00842 if (ARGUMENT_PRESENT( IrpContext )) { 00843 00844 UdfCleanupIrpContext( IrpContext, FALSE ); 00845 } 00846 00847 // 00848 // If we have an Irp then complete the irp. 00849 // 00850 00851 if (ARGUMENT_PRESENT( Irp )) { 00852 00853 // 00854 // Clear the information field in case we have used this Irp 00855 // internally. 00856 // 00857 00858 if (NT_ERROR( Status ) && 00859 FlagOn( Irp->Flags, IRP_INPUT_OPERATION )) { 00860 00861 Irp->IoStatus.Information = 0; 00862 } 00863 00864 Irp->IoStatus.Status = Status; 00865 IoCompleteRequest( Irp, IO_CD_ROM_INCREMENT ); 00866 } 00867 00868 return; 00869 } 00870 00871 00872 VOID 00873 UdfSetThreadContext ( 00874 IN PIRP_CONTEXT IrpContext, 00875 IN PTHREAD_CONTEXT ThreadContext 00876 ) 00877 00878 /*++ 00879 00880 Routine Description: 00881 00882 This routine is called at each Fsd/Fsp entry point set up the IrpContext 00883 and thread local storage to track top level requests. If there is 00884 not a Udfs context in the thread local storage then we use the input one. 00885 Otherwise we use the one already there. This routine also updates the 00886 IrpContext based on the state of the top-level context. 00887 00888 If the TOP_LEVEL flag in the IrpContext is already set when we are called 00889 then we force this request to appear top level. 00890 00891 Arguments: 00892 00893 ThreadContext - Address on stack for local storage if not already present. 00894 00895 ForceTopLevel - We force this request to appear top level regardless of 00896 any previous stack value. 00897 00898 Return Value: 00899 00900 None 00901 00902 --*/ 00903 00904 { 00905 PTHREAD_CONTEXT CurrentThreadContext; 00906 ULONG_PTR StackTop; 00907 ULONG_PTR StackBottom; 00908 00909 PAGED_CODE(); 00910 00911 ASSERT_IRP_CONTEXT( IrpContext ); 00912 00913 // 00914 // Get the current top-level irp out of the thread storage. 00915 // If NULL then this is the top-level request. 00916 // 00917 00918 CurrentThreadContext = (PTHREAD_CONTEXT) IoGetTopLevelIrp(); 00919 00920 if (CurrentThreadContext == NULL) { 00921 00922 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL ); 00923 } 00924 00925 // 00926 // Initialize the input context unless we are using the current 00927 // thread context block. We use the new block if our caller 00928 // specified this or the existing block is invalid. 00929 // 00930 // The following must be true for the current to be a valid Udfs context. 00931 // 00932 // Structure must lie within current stack. 00933 // Address must be ULONG aligned. 00934 // Udfs signature must be present. 00935 // 00936 // If this is not a valid Udfs context then use the input thread 00937 // context and store it in the top level context. 00938 // 00939 00940 IoGetStackLimits( &StackTop, &StackBottom); 00941 00942 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL ) || 00943 (((ULONG_PTR) CurrentThreadContext > StackBottom - sizeof( THREAD_CONTEXT )) || 00944 ((ULONG_PTR) CurrentThreadContext <= StackTop) || 00945 LongOffsetPtr( CurrentThreadContext ) || 00946 (CurrentThreadContext->Udfs != UDFS_SIGNATURE))) { 00947 00948 ThreadContext->Udfs = UDFS_SIGNATURE; 00949 ThreadContext->SavedTopLevelIrp = (PIRP) CurrentThreadContext; 00950 ThreadContext->TopLevelIrpContext = IrpContext; 00951 IoSetTopLevelIrp( (PIRP) ThreadContext ); 00952 00953 IrpContext->TopLevel = IrpContext; 00954 IrpContext->ThreadContext = ThreadContext; 00955 00956 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS ); 00957 00958 // 00959 // Otherwise use the IrpContext in the thread context. 00960 // 00961 00962 } else { 00963 00964 IrpContext->TopLevel = CurrentThreadContext->TopLevelIrpContext; 00965 } 00966 00967 return; 00968 } 00969 00970 00971 BOOLEAN 00972 UdfFastIoCheckIfPossible ( 00973 IN PFILE_OBJECT FileObject, 00974 IN PLARGE_INTEGER FileOffset, 00975 IN ULONG Length, 00976 IN BOOLEAN Wait, 00977 IN ULONG LockKey, 00978 IN BOOLEAN CheckForReadOperation, 00979 OUT PIO_STATUS_BLOCK IoStatus, 00980 IN PDEVICE_OBJECT DeviceObject 00981 ) 00982 00983 /*++ 00984 00985 Routine Description: 00986 00987 This routine checks if fast i/o is possible for a read/write operation 00988 00989 Arguments: 00990 00991 FileObject - Supplies the file object used in the query 00992 00993 FileOffset - Supplies the starting byte offset for the read/write operation 00994 00995 Length - Supplies the length, in bytes, of the read/write operation 00996 00997 Wait - Indicates if we can wait 00998 00999 LockKey - Supplies the lock key 01000 01001 CheckForReadOperation - Indicates if this is a check for a read or write 01002 operation 01003 01004 IoStatus - Receives the status of the operation if our return value is 01005 FastIoReturnError 01006 01007 Return Value: 01008 01009 BOOLEAN - TRUE if fast I/O is possible and FALSE if the caller needs 01010 to take the long route. 01011 01012 --*/ 01013 01014 { 01015 PAGED_CODE(); 01016 01017 return TRUE; 01018 } 01019 01020 01021 ULONG 01022 UdfSerial32 ( 01023 IN PCHAR Buffer, 01024 IN ULONG ByteCount 01025 ) 01026 01027 /*++ 01028 01029 Routine Description: 01030 01031 This routine is called to generate a 32 bit serial number. This is 01032 done by doing four separate checksums into an array of bytes and 01033 then treating the bytes as a ULONG. 01034 01035 Arguments: 01036 01037 Buffer - Pointer to the buffer to generate the ID for. 01038 01039 ByteCount - Number of bytes in the buffer. 01040 01041 Return Value: 01042 01043 ULONG - The 32 bit serial number. 01044 01045 --*/ 01046 01047 { 01048 union { 01049 UCHAR Bytes[4]; 01050 ULONG SerialId; 01051 } Checksum; 01052 01053 PAGED_CODE(); 01054 01055 // 01056 // Initialize the serial number. 01057 // 01058 01059 Checksum.SerialId = 0; 01060 01061 // 01062 // Continue while there are more bytes to use. 01063 // 01064 01065 while (ByteCount--) { 01066 01067 // 01068 // Increment this sub-checksum. 01069 // 01070 01071 Checksum.Bytes[ByteCount & 0x3] += *(Buffer++); 01072 } 01073 01074 // 01075 // Return the checksums as a ULONG. 01076 // 01077 01078 return Checksum.SerialId; 01079 } 01080 01081 01082 VOID 01083 UdfInitializeCrc16 ( 01084 ULONG Polynomial 01085 ) 01086 01087 /*++ 01088 01089 Routine Description: 01090 01091 This routine generates the 16bit CRC Table to be used in CRC calculation. 01092 01093 Arguments: 01094 01095 Polynomial - Starting seed for the generation 01096 01097 Return Value: 01098 01099 None 01100 01101 --*/ 01102 01103 { 01104 ULONG n, i, Crc; 01105 01106 // 01107 // All CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories 01108 // and Ned W. Rhodes of Software Systems Group. It has been published in 01109 // "Design and Validation of Computer Protocols", Prentice Hall, Englewood 01110 // Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4. 01111 // 01112 // Copyright is held by AT&T. 01113 // 01114 // AT&T gives permission for the free use of the source code. 01115 // 01116 01117 UdfCrcTable = (PUSHORT) FsRtlAllocatePoolWithTag( UdfPagedPool, 01118 256 * sizeof(USHORT), 01119 TAG_CRC_TABLE ); 01120 01121 for (n = 0; n < 256; n++) { 01122 01123 Crc = n << 8; 01124 01125 for (i = 0; i < 8; i++) { 01126 01127 if(Crc & 0x8000) { 01128 01129 Crc = (Crc << 1) ^ Polynomial; 01130 01131 } else { 01132 01133 Crc <<= 1; 01134 } 01135 01136 Crc &= 0xffff; 01137 } 01138 01139 UdfCrcTable[n] = (USHORT) Crc; 01140 } 01141 } 01142 01143 01144 01145 USHORT 01146 UdfComputeCrc16 ( 01147 PUCHAR Buffer, 01148 ULONG ByteCount 01149 ) 01150 01151 /*++ 01152 01153 Routine Description: 01154 01155 This routine generates a 16 bit CRC of the input buffer in accordance 01156 with the precomputed CRC table. 01157 01158 Arguments: 01159 01160 Buffer - Pointer to the buffer to generate the CRC for. 01161 01162 ByteCount - Number of bytes in the buffer. 01163 01164 Return Value: 01165 01166 USHORT - The 16bit CRC 01167 01168 --*/ 01169 01170 { 01171 USHORT Crc = 0; 01172 01173 // 01174 // All CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories 01175 // and Ned W. Rhodes of Software Systems Group. It has been published in 01176 // "Design and Validation of Computer Protocols", Prentice Hall, Englewood 01177 // Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4. 01178 // 01179 // Copyright is held by AT&T. 01180 // 01181 // AT&T gives permission for the free use of the source code. 01182 // 01183 01184 while (ByteCount-- > 0) { 01185 01186 Crc = UdfCrcTable[((Crc >> 8) ^ *Buffer++) & 0xff] ^ (Crc << 8); 01187 } 01188 01189 return Crc; 01190 } 01191 01192 01193 USHORT 01194 UdfComputeCrc16Uni ( 01195 PWCHAR Buffer, 01196 ULONG CharCount 01197 ) 01198 01199 /*++ 01200 01201 Routine Description: 01202 01203 This routine generates a 16 bit CRC of the input buffer in accordance 01204 with the precomputed CRC table. 01205 01206 It performs a byte-order independent crc (hi then lo). This is a bit 01207 suspect, but is called for in the specification. 01208 01209 Arguments: 01210 01211 Buffer - Pointer to the buffer to generate the CRC for. 01212 01213 ShortCount - Number of wide characters in the buffer. 01214 01215 Return Value: 01216 01217 USHORT - The 16bit CRC 01218 01219 --*/ 01220 01221 { 01222 USHORT Crc = 0; 01223 01224 // 01225 // Byte order independent CRC, hi byte to low byte per character. 01226 // 01227 01228 while (CharCount-- > 0) { 01229 01230 Crc = UdfCrcTable[((Crc >> 8) ^ (*Buffer >> 8)) & 0xff] ^ (Crc << 8); 01231 Crc = UdfCrcTable[((Crc >> 8) ^ (*Buffer++ & 0xff)) & 0xff] ^ (Crc << 8); 01232 } 01233 01234 return Crc; 01235 } 01236 01237 01238 ULONG 01239 UdfHighBit ( 01240 ULONG Word 01241 ) 01242 01243 /*++ 01244 01245 Routine Description: 01246 01247 This routine discovers the highest set bit of the input word. It is 01248 equivalent to the integer logarithim base 2. 01249 01250 Arguments: 01251 01252 Word - word to check 01253 01254 Return Value: 01255 01256 Bit offset of highest set bit. If no bit is set, return is zero. 01257 01258 --*/ 01259 01260 { 01261 ULONG Offset = 31; 01262 ULONG Mask = (ULONG)(1 << 31); 01263 01264 if (Word == 0) { 01265 01266 return 0; 01267 } 01268 01269 while ((Word & Mask) == 0) { 01270 01271 Offset--; 01272 Mask >>= 1; 01273 } 01274 01275 return Offset; 01276 } 01277 01278 01279 #ifdef UDF_SANITY 01280 BOOLEAN 01281 UdfDebugTrace ( 01282 LONG IndentIncrement, 01283 ULONG TraceMask, 01284 PCHAR Format, 01285 ... 01286 ) 01287 01288 /*++ 01289 01290 Routine Description: 01291 01292 This routine is a simple debug info printer that returns a constant boolean value. This 01293 makes it possible to splice it into the middle of boolean expressions to discover which 01294 elements are firing. 01295 01296 We will use this as our general debug printer. See udfdata.h for how we use the DebugTrace 01297 macro to accomplish the effect. 01298 01299 Arguments: 01300 01301 IndentIncrement - amount to change the indentation by. 01302 01303 TraceMask - specification of what debug trace level this call should be noisy at. 01304 01305 Return Value: 01306 01307 USHORT - The 16bit CRC 01308 01309 --*/ 01310 01311 { 01312 va_list Arglist; 01313 LONG i; 01314 UCHAR Buffer[128]; 01315 int Bytes; 01316 01317 if (TraceMask == 0 || (UdfDebugTraceLevel & TraceMask) != 0) { 01318 01319 if (IndentIncrement < 0) { 01320 01321 UdfDebugTraceIndent += IndentIncrement; 01322 } 01323 01324 if (UdfDebugTraceIndent < 0) { 01325 01326 UdfDebugTraceIndent = 0; 01327 } 01328 01329 // 01330 // Build the indent in big chunks since calling DbgPrint repeatedly is expensive. 01331 // 01332 01333 for (i = UdfDebugTraceIndent; i > 0; i -= (sizeof(Buffer) - 1)) { 01334 01335 RtlFillMemory( Buffer, Min( i, (sizeof(Buffer) - 1 )), ' '); 01336 *(Buffer + Min( i, (sizeof(Buffer) - 1 ))) = '\0'; 01337 01338 DbgPrint( Buffer ); 01339 } 01340 01341 // 01342 // Format the output into a buffer and then print it. 01343 // 01344 01345 va_start( Arglist, Format ); 01346 Bytes = _vsnprintf( Buffer, sizeof(Buffer), Format, Arglist ); 01347 va_end( Arglist ); 01348 01349 // 01350 // detect buffer overflow 01351 // 01352 01353 if (Bytes == -1) { 01354 01355 Buffer[sizeof(Buffer) - 1] = '\n'; 01356 } 01357 01358 DbgPrint( Buffer ); 01359 01360 if (IndentIncrement > 0) { 01361 01362 UdfDebugTraceIndent += IndentIncrement; 01363 } 01364 } 01365 01366 return TRUE; 01367 } 01368 #endif 01369

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