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

ioeapi.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1998 Microsoft Corporation 00004 00005 Module Name: 00006 00007 ioeapi.c 00008 00009 Abstract: 00010 00011 This module contains the code for the exported IoErr APIs 00012 00013 Author: 00014 00015 Michael Tsang (MikeTs) 2-Sep-1998 00016 00017 Environment: 00018 00019 Kernel mode 00020 00021 Revision History: 00022 00023 00024 --*/ 00025 00026 #include "pch.h" 00027 00028 #ifdef ALLOC_PRAGMA 00029 #pragma alloc_text(INIT, IoErrInitSystem) 00030 #pragma alloc_text(PAGE, IoErrMatchErrCase) 00031 #pragma alloc_text(PAGE, IoErrFindErrCaseByID) 00032 #pragma alloc_text(PAGE, IoErrHandleErrCase) 00033 #pragma alloc_text(PAGE, IoErrGetLongErrMessage) 00034 #pragma alloc_text(PAGE, IoErrGetShortErrMessage) 00035 #endif 00036 00037 BOOLEAN 00038 IoErrInitSystem( 00039 VOID 00040 ) 00041 /*++ 00042 00043 Routine Description: 00044 This routine initializes the whole error logging/handling system. 00045 00046 Arguments: 00047 None 00048 00049 Return Value: 00050 Success - returns TRUE 00051 Failure - returns FALSE 00052 00053 --*/ 00054 { 00055 PROCNAME("IoErrInitSystem"); 00056 BOOLEAN rc = TRUE; 00057 00058 ENTER(1, ("()\n")); 00059 00060 KeInitializeSpinLock(&IoepErrListLock); 00061 InitializeListHead(&IoepErrThreadListHead); 00062 InitializeListHead(&IoepErrModuleListHead); 00063 InitializeListHead(&IoepSaveDataListHead); 00064 RtlInitUnicodeString( 00065 &IoepRegKeyStrIoErr, 00066 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES\\IOERR"); 00067 00068 EXIT(1, ("=%x\n", rc)); 00069 return rc; 00070 } //IoErrInitSystem 00071 00072 HANDLE 00073 IoErrInitErrLogByIrp( 00074 IN PIRP Irp, 00075 IN ULONG ulFlags 00076 ) 00077 /*++ 00078 00079 Routine Description: 00080 This routine initializes an error logging session that is keyed by an Irp. 00081 00082 Arguments: 00083 Irp - points to the Irp that is used as the key to the logging session. 00084 ulFlags - log session flags 00085 00086 Return Value: 00087 Success - returns the newly created error log handle. 00088 Failure - returns NULL. 00089 00090 --*/ 00091 { 00092 PROCNAME("IoErrInitErrLogByIrp"); 00093 PERRLOG ErrLog; 00094 00095 ENTER(1, ("(Irp=%p,ulFlags=%x)\n", Irp, ulFlags)); 00096 00097 ErrLog = IoepInitErrLog(THREADKEY_IRP, Irp, ulFlags); 00098 00099 EXIT(1, ("=%p\n", ErrLog)); 00100 return ErrLog; 00101 } //IoErrInitErrLogByIrp 00102 00103 HANDLE 00104 IoErrInitErrLogByThreadID( 00105 IN PKTHREAD ThreadID, 00106 IN ULONG ulFlags 00107 ) 00108 /*++ 00109 00110 Routine Description: 00111 This routine initializes an error logging session that is keyed by thread. 00112 00113 Arguments: 00114 ThreadID - thread ID 00115 ulFlags - log session flags 00116 00117 Return Value: 00118 Success - returns the newly created error log handle. 00119 Failure - returns NULL. 00120 00121 --*/ 00122 { 00123 PROCNAME("IoErrInitErrLogByThreadID"); 00124 PERRLOG ErrLog; 00125 00126 ENTER(1, ("(ThreadID=%p,ulFlags=%x)\n", ThreadID, ulFlags)); 00127 00128 ErrLog = IoepInitErrLog(THREADKEY_THREADID, ThreadID, ulFlags); 00129 00130 EXIT(1, ("=%p\n", ErrLog)); 00131 return ErrLog; 00132 } //IoErrInitErrLogByThreadID 00133 00134 VOID 00135 IoErrLogErrByIrp( 00136 IN PIRP Irp, 00137 IN CONST GUID *ComponentGuid, 00138 IN ULONG ErrCode, 00139 IN PWSTR TextData OPTIONAL, 00140 IN ULONG DataBlkType, 00141 IN ULONG DataBlkLen OPTIONAL, 00142 IN PVOID DataBlock OPTIONAL, 00143 IN CONST GUID *MofGuid OPTIONAL 00144 ) 00145 /*++ 00146 00147 Routine Description: 00148 This routine logs the error data to the error log session identified by 00149 the given Irp. 00150 00151 Arguments: 00152 Irp - points to the Irp that is used as the key to the logging session. 00153 ComponentGuid - points to the component GUID of the caller 00154 ErrCode - unique error code 00155 TextData - points to an optional WSTR of text data 00156 DataBlkType - data type of the data block 00157 DataBlkLen - length of the data block 00158 DataBlock - points to the data block 00159 MofGuid - points to the MOF GUID of the data block if applicable 00160 00161 Return Value: 00162 None 00163 00164 --*/ 00165 { 00166 PROCNAME("IoErrLogErrByIrp"); 00167 00168 ENTER(1, ("(Irp=%p,pGuid=%p,ErrCode=%x,Text=%S,Type=%x,Len=%d,DataBlk=%p,MofGuid=%p)\n", 00169 Irp, ComponentGuid, ErrCode, TextData? TextData: L"", DataBlkType, 00170 DataBlkLen, DataBlock, MofGuid)); 00171 00172 IoepLogErr(THREADKEY_IRP, 00173 Irp, 00174 ComponentGuid, 00175 ErrCode, 00176 TextData, 00177 DataBlkType, 00178 DataBlkLen, 00179 DataBlock, 00180 MofGuid); 00181 00182 EXIT(1, ("!\n")); 00183 } //IoErrLogErrByIrp 00184 00185 VOID 00186 IoErrLogErrByThreadID( 00187 IN PKTHREAD ThreadID, 00188 IN CONST GUID *ComponentGuid, 00189 IN ULONG ErrCode, 00190 IN PWSTR TextData OPTIONAL, 00191 IN ULONG DataBlkType, 00192 IN ULONG DataBlkLen OPTIONAL, 00193 IN PVOID DataBlock OPTIONAL, 00194 IN CONST GUID *MofGuid OPTIONAL 00195 ) 00196 /*++ 00197 00198 Routine Description: 00199 This routine logs the error data to the error log session identified by 00200 the given ThreadID. 00201 00202 Arguments: 00203 ThreadID - points to the ThreadID that is used as the key to the logging 00204 session. 00205 ComponentGuid - points to the component GUID of the caller 00206 ErrCode - unique error code 00207 TextData - points to an optional WSTR of text data 00208 DataBlkType - data type of the data block 00209 DataBlkLen - length of the data block 00210 DataBlock - points to the data block 00211 MofGuid - points to the MOF GUID of the data block if applicable 00212 00213 Return Value: 00214 None 00215 00216 --*/ 00217 { 00218 PROCNAME("IoErrLogErrByThreadID"); 00219 00220 ENTER(1, ("(ThreadID=%p,pGuid=%p,ErrCode=%x,Text=%S,Type=%x,Len=%d,DataBlk=%p,MofGuid=%p)\n", 00221 ThreadID, ComponentGuid, ErrCode, TextData? TextData: L"", 00222 DataBlkType, DataBlkLen, DataBlock, MofGuid)); 00223 00224 IoepLogErr(THREADKEY_THREADID, 00225 ThreadID, 00226 ComponentGuid, 00227 ErrCode, 00228 TextData, 00229 DataBlkType, 00230 DataBlkLen, 00231 DataBlock, 00232 MofGuid); 00233 00234 EXIT(1, ("!\n")); 00235 } //IoErrLogErrByThreadID 00236 00237 VOID 00238 IoErrPropagateErrLog( 00239 IN HANDLE ErrLogHandle 00240 ) 00241 /*++ 00242 00243 Routine Description: 00244 This routine propagates the error log stack from the current error log 00245 session to the next nested error log session. 00246 00247 Arguments: 00248 ErrLogHandle - points to the error log session 00249 00250 Return Value: 00251 None 00252 00253 --*/ 00254 { 00255 PROCNAME("IoErrPropagateErrLog"); 00256 PERRLOG ErrLog = (PERRLOG)ErrLogHandle; 00257 00258 ASSERT(ErrLogHandle != NULL); 00259 ASSERT(((PERRLOG)ErrLogHandle)->Signature == SIG_ERRLOG); 00260 ENTER(1, ("(ErrLog=%p)\n", ErrLogHandle)); 00261 00262 if ((ErrLog != NULL) && (ErrLog->Signature == SIG_ERRLOG)) 00263 { 00264 PERRENTRY ErrStack; 00265 KIRQL Irql; 00266 00267 ExAcquireSpinLock(&IoepErrListLock, &Irql); 00268 ErrStack = IoepGetErrStack((PERRLOG)ErrLogHandle); 00269 if (ErrStack != NULL) 00270 { 00271 PERRLOG ErrLogNext; 00272 00273 ErrLogNext = CONTAINING_RECORD(ErrLog->list.Flink, ERRLOG, list); 00274 if (&ErrLogNext->list != &ErrLog->ErrThread->ErrLogListHead) 00275 { 00276 PSINGLE_LIST_ENTRY ErrTail; 00277 00278 for (ErrTail = &ErrStack->slist; 00279 ErrTail->Next != NULL; 00280 ErrTail = ErrTail->Next) 00281 ; 00282 00283 ErrTail->Next = ErrLogNext->ErrStack.Next; 00284 ErrLogNext->ErrStack.Next = ErrStack->slist.Next; 00285 ErrLog->ErrStack.Next = NULL; 00286 if (ErrLog->ErrInfo != NULL) 00287 { 00288 ErrLog->ErrInfo->Signature = 0; 00289 ExFreePool(ErrLog->ErrInfo); 00290 ErrLog->ErrInfo = NULL; 00291 } 00292 } 00293 } 00294 ExReleaseSpinLock(&IoepErrListLock, Irql); 00295 } 00296 else 00297 { 00298 DBGPRINT(("invalid handle\n")) 00299 } 00300 00301 EXIT(1, ("!\n")); 00302 } //IoErrPropagateErrLog 00303 00304 VOID 00305 IoErrTerminateErrLog( 00306 IN HANDLE ErrLogHandle 00307 ) 00308 /*++ 00309 00310 Routine Description: 00311 This routine terminates an error log session. 00312 00313 Arguments: 00314 ErrLogHandle - points to the error log session 00315 00316 Return Value: 00317 None 00318 00319 --*/ 00320 { 00321 PROCNAME("IoErrTerminateErrLog"); 00322 PERRLOG ErrLog = (PERRLOG)ErrLogHandle; 00323 00324 ASSERT(ErrLogHandle != NULL); 00325 ASSERT(((PERRLOG)ErrLogHandle)->Signature == SIG_ERRLOG); 00326 ENTER(1, ("(ErrLog=%p)\n", ErrLogHandle)); 00327 00328 if ((ErrLog != NULL) && (ErrLog->Signature == SIG_ERRLOG)) 00329 { 00330 PERRENTRY ErrStack; 00331 KIRQL Irql; 00332 00333 ErrStack = IoepGetErrStack(ErrLog); 00334 if (ErrStack != NULL) 00335 { 00336 // 00337 // If we are at the top level log session by Irp and we have an 00338 // error, we fire a WMI event. 00339 // 00340 if ((ErrLog->ErrThread->ThreadKeyType == THREADKEY_IRP) && 00341 (ErrLog->list.Flink == &ErrLog->ErrThread->ErrLogListHead)) 00342 { 00343 PDEVICE_NODE DevNode; 00344 00345 ASSERT_PDO(ErrLog->ErrThread->ThreadKey.IrpKey.TargetDevice); 00346 DevNode = ErrLog->ErrThread->ThreadKey.IrpKey.TargetDevice->DeviceObjectExtension->DeviceNode; 00347 IoepFireWMIEvent(IoErrGetErrData(ErrLogHandle), 00348 DevNode->InstancePath.Buffer); 00349 } 00350 00351 ErrLog->ErrStack.Next = NULL; 00352 IoepFreeErrStack(ErrStack); 00353 } 00354 00355 ExAcquireSpinLock(&IoepErrListLock, &Irql); 00356 if (ErrLog->ErrInfo != NULL) 00357 { 00358 ErrLog->ErrInfo->Signature = 0; 00359 ExFreePool(ErrLog->ErrInfo); 00360 ErrLog->ErrInfo = NULL; 00361 } 00362 00363 RemoveEntryList(&ErrLog->list); 00364 if (IsListEmpty(&ErrLog->ErrThread->ErrLogListHead)) 00365 { 00366 RemoveEntryList(&ErrLog->ErrThread->list); 00367 ExFreePool(ErrLog->ErrThread); 00368 ErrLog->ErrThread = NULL; 00369 } 00370 ErrLog->Signature = 0; 00371 ExFreePool(ErrLog); 00372 ExReleaseSpinLock(&IoepErrListLock, Irql); 00373 } 00374 else 00375 { 00376 DBGPRINT(("invalid handle\n")) 00377 } 00378 00379 EXIT(1, ("!\n")); 00380 } //IoErrTerminateErrLog 00381 00382 NTSTATUS 00383 IoErrRegisterErrHandlers( 00384 IN CONST GUID *ComponentGuid, 00385 IN ULONG NumErrHandlers, 00386 IN PERRHANDLER *HandlerTable 00387 ) 00388 /*++ 00389 00390 Routine Description: 00391 This routine registers error handlers for the caller module. 00392 00393 Arguments: 00394 ComponentGuid - points to the GUID of the caller component 00395 NumErrHandlers - number of error handlers in the table 00396 HandlerTable - points to the error handler table 00397 00398 Return Value: 00399 Success - returns STATUS_SUCCESS 00400 Failure - returns NT status code 00401 00402 --*/ 00403 { 00404 PROCNAME("IoErrRegisterErrHandlers"); 00405 NTSTATUS status; 00406 PERRMODULE ErrModule; 00407 00408 ASSERT(ComponentGuid != NULL); 00409 ASSERT(NumErrHandlers > 0); 00410 ASSERT(HandlerTable != NULL); 00411 ENTER(1, ("(pGuid=%p,NumHandlers=%d,HandleTable=%p)\n", 00412 ComponentGuid, NumErrHandlers, HandlerTable)); 00413 00414 ErrModule = IoepFindErrModule(ComponentGuid); 00415 if (ErrModule == NULL) 00416 { 00417 ErrModule = ExAllocatePoolWithTag( 00418 NonPagedPool, 00419 sizeof(ERRMODULE) + 00420 sizeof(PERRHANDLER)*(NumErrHandlers - 1), 00421 IOETAG_ERRMODULE); 00422 00423 if (ErrModule != NULL) 00424 { 00425 ErrModule->ComponentGuid = *ComponentGuid; 00426 ErrModule->NumErrHandlers = NumErrHandlers; 00427 RtlCopyMemory(ErrModule->HandlerTable, 00428 HandlerTable, 00429 sizeof(PERRHANDLER)*NumErrHandlers); 00430 ExInterlockedInsertTailList(&IoepErrModuleListHead, 00431 &ErrModule->list, 00432 &IoepErrListLock); 00433 status = STATUS_SUCCESS; 00434 } 00435 else 00436 { 00437 status = STATUS_INSUFFICIENT_RESOURCES; 00438 DBGPRINT(("failed to allocate error module\n")); 00439 } 00440 } 00441 else 00442 { 00443 status = STATUS_IOE_MODULE_ALREADY_REGISTERED; 00444 DBGPRINT(("error module already registered\n")); 00445 } 00446 00447 EXIT(1, ("=%x\n", status)); 00448 return status; 00449 } //IoErrRegisterErrHandlers 00450 00451 PERRINFO 00452 IoErrGetErrData( 00453 IN HANDLE ErrLogHandle 00454 ) 00455 /*++ 00456 00457 Routine Description: 00458 This routine returns the error data from the error log session. 00459 00460 Arguments: 00461 ErrLogHandle - points to the error log session 00462 00463 Return Value: 00464 Success - returns pointer to the error info structure 00465 Failure - returns NULL 00466 00467 --*/ 00468 { 00469 PROCNAME("IoErrGetErrData"); 00470 PERRINFO ErrInfo = NULL; 00471 PERRLOG ErrLog = (PERRLOG)ErrLogHandle; 00472 00473 ASSERT(ErrLogHandle != NULL); 00474 ASSERT(((PERRLOG)ErrLogHandle)->Signature == SIG_ERRLOG); 00475 ENTER(1, ("(ErrLog=%p)\n", ErrLogHandle)); 00476 00477 if ((ErrLog != NULL) && (ErrLog->Signature == SIG_ERRLOG)) 00478 { 00479 if (ErrLog->ErrInfo != NULL) 00480 { 00481 ErrInfo = ErrLog->ErrInfo; 00482 } 00483 else 00484 { 00485 NTSTATUS status; 00486 ULONG len; 00487 00488 status = IoepExtractErrData(IoepGetErrStack(ErrLog), 00489 NULL, 00490 0, 00491 &len); 00492 if (status == STATUS_BUFFER_TOO_SMALL) 00493 { 00494 ErrInfo = ExAllocatePoolWithTag(NonPagedPool, 00495 len, 00496 IOETAG_ERRINFO); 00497 if (ErrInfo != NULL) 00498 { 00499 status = IoepExtractErrData( 00500 IoepGetErrStack(ErrLog), 00501 ErrInfo, 00502 len, 00503 NULL); 00504 if (NT_SUCCESS(status)) 00505 { 00506 ErrLog->ErrInfo = ErrInfo; 00507 } 00508 else 00509 { 00510 ExFreePool(ErrInfo); 00511 ErrInfo = NULL; 00512 DBGPRINT(("failed to get error data (rc=%x)\n", 00513 status)); 00514 } 00515 } 00516 else 00517 { 00518 DBGPRINT(("failed to allocate error info buffer (len=%d)\n", 00519 len)); 00520 } 00521 } 00522 else 00523 { 00524 DBGPRINT(("failed to determine error data size (rc=%x)\n", status)); 00525 } 00526 } 00527 } 00528 else 00529 { 00530 DBGPRINT(("invalid handle\n")) 00531 } 00532 00533 EXIT(1, ("=%p\n", ErrInfo)); 00534 return ErrInfo; 00535 } //IoErrGetErrData 00536 00537 HANDLE 00538 IoErrSaveErrData( 00539 IN HANDLE ErrLogHandle, 00540 IN PVOID DataTag OPTIONAL, 00541 IN ULONG TagFlags OPTIONAL 00542 ) 00543 /*++ 00544 00545 Routine Description: 00546 This routine saves the error data and returns a handle to the saved data. 00547 00548 Arguments: 00549 ErrLogHandle - points to the error log session 00550 DataTag - tag to be associated with for the saved error data 00551 KeyFlags - flags about the DataTag: 00552 IOEDATATAG_TYPE_DEVNODE - DataTag is a DevNode pointer 00553 00554 Return Value: 00555 Success - returns the detached error log handle 00556 Failure - returns NULL 00557 00558 --*/ 00559 { 00560 PROCNAME("IoErrSaveErrData"); 00561 PSAVEDATA SaveData = NULL; 00562 00563 ASSERT(ErrLogHandle != NULL); 00564 ASSERT(((PERRLOG)ErrLogHandle)->Signature == SIG_ERRLOG); 00565 ASSERT((TagFlags & ~IOEDATATAG_BITS) == 0); 00566 ENTER(1, ("(ErrLog=%p,DataTag=%p,TagFlags=%x)\n", 00567 ErrLogHandle, DataTag, TagFlags)); 00568 00569 if ((ErrLogHandle != NULL) && 00570 (((PERRLOG)ErrLogHandle)->Signature == SIG_ERRLOG)) 00571 { 00572 PERRINFO ErrInfo; 00573 00574 ErrInfo = IoErrGetErrData(ErrLogHandle); 00575 if (ErrInfo != NULL) 00576 { 00577 SaveData = ExAllocatePoolWithTag(NonPagedPool, 00578 sizeof(SAVEDATA), 00579 IOETAG_SAVEDATA); 00580 if (SaveData != NULL) 00581 { 00582 ErrInfo->DataTag = DataTag; 00583 ErrInfo->TagFlags = TagFlags & IOEDATATAG_TYPE_MASK; 00584 SaveData->Signature = SIG_SAVEDATA; 00585 SaveData->ErrInfo = ErrInfo; 00586 ((PERRLOG)ErrLogHandle)->ErrInfo = NULL; 00587 ExInterlockedInsertHeadList(&IoepSaveDataListHead, 00588 &SaveData->list, 00589 &IoepErrListLock); 00590 } 00591 else 00592 { 00593 DBGPRINT(("failed to allocate save data block\n")); 00594 } 00595 } 00596 } 00597 else 00598 { 00599 DBGPRINT(("invalid handle\n")) 00600 } 00601 00602 EXIT(1, ("=%p\n", SaveData)); 00603 return SaveData; 00604 } //IoErrSaveErrData 00605 00606 PERRINFO 00607 IoErrGetSavedData( 00608 IN HANDLE SaveDataHandle 00609 ) 00610 /*++ 00611 00612 Routine Description: 00613 This routine returns the error info. from the saved error data. 00614 00615 Arguments: 00616 SaveDataHandle - points to the saved error data 00617 00618 Return Value: 00619 Success - returns a pointer to the saved error info. 00620 Failure - returns NULL 00621 00622 --*/ 00623 { 00624 PROCNAME("IoErrGetSavedData"); 00625 PERRINFO ErrInfo; 00626 00627 ASSERT(SaveDataHandle != NULL); 00628 ASSERT(((PSAVEDATA)SaveDataHandle)->Signature == SIG_SAVEDATA); 00629 ENTER(1, ("(SaveData=%p)\n", SaveDataHandle)); 00630 00631 if ((SaveDataHandle != NULL) && 00632 (((PSAVEDATA)SaveDataHandle)->Signature == SIG_SAVEDATA)) 00633 { 00634 ErrInfo = ((PSAVEDATA)SaveDataHandle)->ErrInfo; 00635 } 00636 else 00637 { 00638 ErrInfo = NULL; 00639 DBGPRINT(("invalid handle\n")) 00640 } 00641 00642 EXIT(1, ("=%p\n", ErrInfo)); 00643 return ErrInfo; 00644 } //IoErrGetSavedData 00645 00646 VOID 00647 IoErrFreeSavedData( 00648 IN HANDLE SaveDataHandle 00649 ) 00650 /*++ 00651 00652 Routine Description: 00653 This routine frees the storage associated with the saved error data. 00654 This function should only be call if the error data has been previously 00655 saved via IoErrSaveErrData. 00656 00657 Arguments: 00658 SaveDataHandle - points to the save data 00659 00660 Return Value: 00661 None 00662 00663 --*/ 00664 { 00665 PROCNAME("IoErrFreeSavedData"); 00666 PSAVEDATA SaveData = (PSAVEDATA)SaveDataHandle; 00667 00668 ASSERT(SaveDataHandle != NULL); 00669 ASSERT(((PSAVEDATA)SaveDataHandle)->Signature == SIG_SAVEDATA); 00670 ENTER(1, ("(SaveData=%p)\n", SaveDataHandle)); 00671 00672 if ((SaveDataHandle != NULL) && 00673 (((PSAVEDATA)SaveDataHandle)->Signature == SIG_SAVEDATA)) 00674 { 00675 KIRQL Irql; 00676 00677 ExAcquireSpinLock(&IoepErrListLock, &Irql); 00678 RemoveEntryList(&SaveData->list); 00679 if (SaveData->ErrInfo != NULL) 00680 { 00681 SaveData->ErrInfo->Signature = 0; 00682 ExFreePool(SaveData->ErrInfo); 00683 SaveData->ErrInfo = NULL; 00684 } 00685 SaveData->Signature = 0; 00686 ExFreePool(SaveData); 00687 ExReleaseSpinLock(&IoepErrListLock, Irql); 00688 } 00689 else 00690 { 00691 DBGPRINT(("invalid handle\n")) 00692 } 00693 00694 EXIT(1, ("!\n")); 00695 } //IoErrFreeSavedData 00696 00697 NTSTATUS 00698 IoErrRetrieveSavedData( 00699 OUT PINFOBLK InfoBlk, 00700 IN ULONG BuffSize, 00701 OUT PULONG DataSize OPTIONAL, 00702 IN PVOID DataTag OPTIONAL, 00703 IN ULONG TagFlags OPTIONAL 00704 ) 00705 /*++ 00706 00707 Routine Description: 00708 This routine returns the saved error info. in the given buffer. If no 00709 DataTag is given, data of all saved error info. are returned. Otherwise, 00710 only the data of the error info. which matches the data tag is returned. 00711 00712 Arguments: 00713 InfoBlk - points to the buffer to receive the data 00714 BuffSize - specifies the size of the buffer 00715 DataSize - points to the variable to receive the actual data size 00716 DataTag - tag associated with the data info. 00717 TagFlags - tag flags 00718 00719 Return Value: 00720 Success - returns STATUS_SUCCESS 00721 Failure - returns NT status code 00722 00723 --*/ 00724 { 00725 PROCNAME("IoErrRetrieveSavedData"); 00726 NTSTATUS status = STATUS_SUCCESS; 00727 PLIST_ENTRY list; 00728 ULONG len, i; 00729 PSAVEDATA SaveData; 00730 00731 ASSERT((InfoBlk != NULL) && (BuffSize > 0) || (DataSize != NULL)); 00732 ENTER(1, ("(Buff=%p,BuffSize=%d,pDataSize=%p,DataTag=%p,TagFlags=%x)\n", 00733 InfoBlk, BuffSize, DataSize, DataTag, TagFlags)); 00734 00735 for (list = IoepSaveDataListHead.Flink, 00736 len = sizeof(INFOBLK) - sizeof(ERRINFO), 00737 i = 0; 00738 list != &IoepSaveDataListHead; 00739 list = list->Flink) 00740 { 00741 SaveData = CONTAINING_RECORD(list, SAVEDATA, list); 00742 if ((DataTag == NULL) || 00743 (DataTag == SaveData->ErrInfo->DataTag) && 00744 (TagFlags == SaveData->ErrInfo->TagFlags & IOEDATATAG_TYPE_MASK)) 00745 { 00746 i++; 00747 len += SaveData->ErrInfo->Size; 00748 } 00749 } 00750 00751 if (len <= BuffSize) 00752 { 00753 if ((InfoBlk != NULL) && (BuffSize > 0)) 00754 { 00755 PERRINFO ErrInfo; 00756 00757 InfoBlk->Signature = SIG_INFOBLK; 00758 InfoBlk->Version = IOE_INFOBLK_VERSION; 00759 InfoBlk->Size = len; 00760 InfoBlk->NumErrInfos = i; 00761 00762 for (list = IoepSaveDataListHead.Flink, 00763 ErrInfo = &InfoBlk->ErrInfos[0]; 00764 list != &IoepSaveDataListHead; 00765 list = list->Flink) 00766 { 00767 SaveData = CONTAINING_RECORD(list, SAVEDATA, list); 00768 if ((DataTag == NULL) || 00769 (DataTag == SaveData->ErrInfo->DataTag) && 00770 (TagFlags == SaveData->ErrInfo->TagFlags & 00771 IOEDATATAG_TYPE_MASK)) 00772 { 00773 RtlCopyMemory(ErrInfo, 00774 SaveData->ErrInfo, 00775 SaveData->ErrInfo->Size); 00776 ErrInfo = (PERRINFO)((PUCHAR)ErrInfo + 00777 SaveData->ErrInfo->Size); 00778 } 00779 } 00780 } 00781 00782 status = STATUS_SUCCESS; 00783 } 00784 else 00785 { 00786 status = STATUS_BUFFER_TOO_SMALL; 00787 DBGPRINT(("buffer too small (size=%d,need=%d)\n", BuffSize, len)); 00788 } 00789 00790 if (DataSize != NULL) 00791 { 00792 *DataSize = len; 00793 } 00794 00795 EXIT(1, ("=%x(len=%d)\n", status, len)); 00796 return status; 00797 } //IoErrRetrievedSavedData 00798 00799 NTSTATUS 00800 IoErrMatchErrCase( 00801 IN PERRINFO ErrInfo, 00802 OUT PULONG ErrCaseID, 00803 OUT PHANDLE ErrCaseHandle OPTIONAL 00804 ) 00805 /*++ 00806 00807 Routine Description: 00808 This routine gets the indexed error entry from the error stack. 00809 00810 Arguments: 00811 ErrInfo - points to the error info. 00812 ErrCaseID - points to the variable to receive the error case ID 00813 ErrCaseHandle - points to the variable to receive the error case handle 00814 00815 Return Value: 00816 Success - returns STATUS_SUCCESS 00817 Failure - returns NT status code 00818 00819 --*/ 00820 { 00821 PROCNAME("IoErrMatchErrCase"); 00822 NTSTATUS status; 00823 00824 ASSERT(ErrInfo != NULL); 00825 ASSERT(ErrInfo->Signature == SIG_ERRINFO); 00826 ASSERT(ErrCaseID != NULL); 00827 PAGED_CODE(); 00828 ENTER(1, ("(ErrInfo=%p,pErrCaseID=%p,pErrCaseHandle=%p)\n", 00829 ErrInfo, ErrCaseID, ErrCaseHandle)); 00830 00831 if ((ErrInfo != NULL) && (ErrInfo->Signature == SIG_ERRINFO)) 00832 { 00833 PERRCASEDB ErrCaseDB = IoepGetErrCaseDB(); 00834 00835 if (ErrCaseDB != NULL) 00836 { 00837 PERRCASE ErrCaseTable; 00838 PERRID ErrIDPath; 00839 ULONG i; 00840 00841 ErrCaseTable = (PERRCASE)((ULONG_PTR)ErrCaseDB + 00842 ErrCaseDB->ErrCaseOffset); 00843 00844 for (i = 0, status = STATUS_NOT_FOUND; i < ErrCaseDB->NumErrCases; ++i) 00845 { 00846 ErrIDPath = (PERRID)((ULONG_PTR)ErrCaseDB + 00847 ErrCaseDB->ErrIDPathBlkOffset + 00848 ErrCaseTable[i].ErrIDPathOffset); 00849 00850 if (IoepMatchErrIDPath(ErrInfo, 00851 ErrIDPath, 00852 ErrCaseTable[i].NumErrIDs)) 00853 { 00854 *ErrCaseID = ErrCaseTable[i].ErrCaseID; 00855 if (ErrCaseHandle != NULL) 00856 { 00857 *ErrCaseHandle = &ErrCaseTable[i]; 00858 } 00859 status = STATUS_SUCCESS; 00860 break; 00861 } 00862 } 00863 } 00864 else 00865 { 00866 status = STATUS_IOE_DATABASE_NOT_READY; 00867 DBGPRINT(("error case database not ready\n")); 00868 } 00869 } 00870 else 00871 { 00872 status = STATUS_INVALID_PARAMETER; 00873 DBGPRINT(("invalid handle\n")) 00874 } 00875 00876 EXIT(1, ("=%x(ErrCaseID=%x,ErrCase=%p)\n", 00877 status, *ErrCaseID, ErrCaseHandle? *ErrCaseHandle: 0)); 00878 return status; 00879 } //IoErrMatchErrCase 00880 00881 NTSTATUS 00882 IoErrFindErrCaseByID( 00883 IN ULONG ErrCaseID, 00884 OUT PHANDLE ErrCaseHandle 00885 ) 00886 /*++ 00887 00888 Routine Description: 00889 This routine finds an error case by the error case ID and returns the 00890 handle to the error case. 00891 00892 Arguments: 00893 ErrCaseID - unique error case ID 00894 ErrCaseHandle - points to the variable to receive the error case handle 00895 00896 Return Value: 00897 Success - returns STATUS_SUCCESS 00898 Failure - returns NT status code 00899 00900 --*/ 00901 { 00902 PROCNAME("IoErrFindErrCaseByID"); 00903 NTSTATUS status; 00904 PERRCASEDB ErrCaseDB; 00905 00906 PAGED_CODE(); 00907 ENTER(1, ("(ErrCaseID=%x,pErrCaseHandle=%p)\n", ErrCaseID, ErrCaseHandle)); 00908 00909 ErrCaseDB = IoepGetErrCaseDB(); 00910 if (ErrCaseDB != NULL) 00911 { 00912 PERRCASE ErrCaseTable; 00913 ULONG i; 00914 00915 ErrCaseTable = (PERRCASE)((ULONG_PTR)ErrCaseDB + 00916 ErrCaseDB->ErrCaseOffset); 00917 00918 for (i = 0, status = STATUS_NOT_FOUND; i < ErrCaseDB->NumErrCases; ++i) 00919 { 00920 if (ErrCaseTable[i].ErrCaseID == ErrCaseID) 00921 { 00922 *ErrCaseHandle = &ErrCaseTable[i]; 00923 status = STATUS_SUCCESS; 00924 break; 00925 } 00926 } 00927 } 00928 else 00929 { 00930 status = STATUS_IOE_DATABASE_NOT_READY; 00931 DBGPRINT(("error case database not ready\n")); 00932 } 00933 00934 EXIT(1, ("=%x(ErrCase=%p)\n", status, *ErrCaseHandle)); 00935 return status; 00936 } //IoErrFindErrCaseByID 00937 00938 NTSTATUS 00939 IoErrHandleErrCase( 00940 IN PERRINFO ErrInfo, 00941 IN HANDLE ErrCaseHandle 00942 ) 00943 /*++ 00944 00945 Routine Description: 00946 This routine handles an error case by executing the resolution method. 00947 00948 Arguments: 00949 ErrInfo - points to the error info. 00950 ErrCaseHandle - points to the error case handle 00951 00952 Return Value: 00953 Success - returns STATUS_SUCCESS 00954 Failure - returns NT status code 00955 00956 --*/ 00957 { 00958 PROCNAME("IoErrHandleErrCase"); 00959 NTSTATUS status; 00960 00961 ASSERT(ErrInfo != NULL); 00962 ASSERT(ErrInfo->Signature == SIG_ERRINFO); 00963 ASSERT(ErrCaseHandle != NULL); 00964 PAGED_CODE(); 00965 ENTER(1, ("(ErrInfo=%p,ErrCase=%p)\n", ErrInfo, ErrCaseHandle)); 00966 00967 if ((ErrInfo != NULL) && (ErrInfo->Signature == SIG_ERRINFO)) 00968 { 00969 status = IoepHandleErrCase(ErrInfo, 00970 (PERRCASE)ErrCaseHandle, 00971 IOEMETHOD_ANY, 00972 NULL); 00973 } 00974 else 00975 { 00976 status = STATUS_INVALID_PARAMETER; 00977 DBGPRINT(("invalid handle\n")) 00978 } 00979 00980 EXIT(1, ("=%x\n", status)); 00981 return status; 00982 } //IoErrHandleErrCase 00983 00984 NTSTATUS 00985 IoErrGetLongErrMessage( 00986 IN PERRINFO ErrInfo, 00987 IN HANDLE ErrCaseHandle, 00988 OUT PUNICODE_STRING unicodeMsg 00989 ) 00990 /*++ 00991 00992 Routine Description: 00993 This routine handles the error case by executing the long message method 00994 and returns the resulting message. 00995 00996 Arguments: 00997 ErrInfo - points to the error info. 00998 ErrCaseHandle - points to the error case handle 00999 unicodeMsg - points to the uninitialized unicode string message buffer 01000 01001 Return Value: 01002 Success - returns STATUS_SUCCESS 01003 Failure - returns NT status code 01004 01005 Note: 01006 This routine will allocate the actual string buffer of the unicode message. 01007 Therefore, it is the caller's responsibility to free the message buffer 01008 via RtlFreeUnicodeString. 01009 01010 --*/ 01011 { 01012 PROCNAME("IoErrGetLongErrMessage"); 01013 NTSTATUS status; 01014 01015 ASSERT(ErrInfo != NULL); 01016 ASSERT(ErrInfo->Signature == SIG_ERRINFO); 01017 ASSERT(ErrCaseHandle != NULL); 01018 ASSERT(unicodeMsg != NULL); 01019 PAGED_CODE(); 01020 ENTER(1, ("(ErrInfo=%p,ErrCase=%p,pMsg=%p)\n", 01021 ErrInfo, ErrCaseHandle, unicodeMsg)); 01022 01023 if ((ErrInfo != NULL) && (ErrInfo->Signature == SIG_ERRINFO)) 01024 { 01025 status = IoepHandleErrCase(ErrInfo, 01026 (PERRCASE)ErrCaseHandle, 01027 IOEMETHOD_LONGMSG, 01028 unicodeMsg); 01029 } 01030 else 01031 { 01032 status = STATUS_INVALID_PARAMETER; 01033 DBGPRINT(("invalid handle\n")) 01034 } 01035 01036 EXIT(1, ("=%x(Msg=%S)\n", status, unicodeMsg->Buffer)); 01037 return status; 01038 } //IoErrGetLongErrMessage 01039 01040 NTSTATUS 01041 IoErrGetShortErrMessage( 01042 IN PERRINFO ErrInfo, 01043 IN HANDLE ErrCaseHandle, 01044 OUT PUNICODE_STRING unicodeMsg 01045 ) 01046 /*++ 01047 01048 Routine Description: 01049 This routine handles the error case by executing the short message method 01050 and returns the resulting message. 01051 01052 Arguments: 01053 ErrInfo - points to the error info. 01054 ErrCaseHandle - points to the error case handle 01055 unicodeMsg - points to the uninitialized unicode string message buffer 01056 01057 Return Value: 01058 Success - returns STATUS_SUCCESS 01059 Failure - returns NT status code 01060 01061 Note: 01062 This routine will allocate the actual string buffer of the unicode message. 01063 Therefore, it is the caller's responsibility to free the message buffer 01064 via RtlFreeUnicodeString. 01065 01066 --*/ 01067 { 01068 PROCNAME("IoErrGetShortErrMessage"); 01069 NTSTATUS status; 01070 01071 ASSERT(ErrInfo != NULL); 01072 ASSERT(ErrInfo->Signature == SIG_ERRINFO); 01073 ASSERT(ErrCaseHandle != NULL); 01074 ASSERT(unicodeMsg != NULL); 01075 PAGED_CODE(); 01076 ENTER(1, ("(ErrInfo=%p,ErrCase=%p,pMsg=%p)\n", 01077 ErrInfo, ErrCaseHandle, unicodeMsg)); 01078 01079 if ((ErrInfo != NULL) && (ErrInfo->Signature == SIG_ERRINFO)) 01080 { 01081 status = IoepHandleErrCase(ErrInfo, 01082 (PERRCASE)ErrCaseHandle, 01083 IOEMETHOD_SHORTMSG, 01084 unicodeMsg); 01085 } 01086 else 01087 { 01088 status = STATUS_INVALID_PARAMETER; 01089 DBGPRINT(("invalid handle\n")) 01090 } 01091 01092 EXIT(1, ("=%x(Msg=%S)\n", status, unicodeMsg->Buffer)); 01093 return status; 01094 } //IoErrGetShortErrMessage

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