00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
#include "pch.h"
00027
00028
#ifdef ALLOC_PRAGMA
00029
#pragma alloc_text(PAGE, IoepHandleErrCase)
00030
#pragma alloc_text(PAGE, IoepFindErrHandler)
00031
#pragma alloc_text(PAGE, IoepMatchErrIDPath)
00032
#pragma alloc_text(PAGE, IoepGetErrMessage)
00033
#pragma alloc_text(PAGE, IoepCatMsgArg)
00034
#pragma alloc_text(PAGE, IoepUnicodeStringCatN)
00035
#pragma alloc_text(PAGE, IoepGetErrCaseDB)
00036
#endif
00037
00038 HANDLE
00039 IoepInitErrLog(
00040 IN ULONG KeyType,
00041 IN PVOID Key,
00042 IN ULONG ulFlags
00043 )
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 {
00060
PROCNAME(
"IoepInitErrLog");
00061
PERRLOG ErrLog;
00062
00063
ASSERT(
Key !=
NULL);
00064
ASSERT(ulFlags & ~
LOGF_INITMASK == 0);
00065
ENTER(2, (
"(KeyType=%x,Key=%p,ulFlags=%x)\n", KeyType,
Key, ulFlags));
00066
00067 ErrLog =
ExAllocatePoolWithTag(
NonPagedPool,
00068
sizeof(
ERRLOG),
00069
IOETAG_ERRLOG);
00070
00071
if (ErrLog !=
NULL)
00072 {
00073
PERRTHREAD ErrThread;
00074
00075 ErrThread =
IoepFindErrThread(KeyType,
Key);
00076
if (ErrThread ==
NULL)
00077 {
00078 ErrThread =
IoepNewErrThread(KeyType,
Key);
00079 }
00080
00081
if (ErrThread !=
NULL)
00082 {
00083 ErrLog->
Signature =
SIG_ERRLOG;
00084 ErrLog->
ulFlags = ulFlags &
LOGF_INITMASK;
00085 ErrLog->
ErrThread = ErrThread;
00086 ErrLog->
ErrStack.Next =
NULL;
00087 ErrLog->
ErrInfo =
NULL;
00088
ExInterlockedInsertHeadList(&ErrThread->
ErrLogListHead,
00089 &ErrLog->
list,
00090 &
IoepErrListLock);
00091 }
00092
else
00093 {
00094
ExFreePool(ErrLog);
00095 ErrLog =
NULL;
00096 }
00097 }
00098
else
00099 {
00100
DBGPRINT((
"failed to allocate new error log\n"));
00101 }
00102
00103
EXIT(2, (
"=%p\n", ErrLog));
00104
return ErrLog;
00105 }
00106
00107
PERRTHREAD
00108 IoepFindErrThread(
00109 IN ULONG KeyType,
00110 IN PVOID Key
00111 )
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 {
00127
PROCNAME(
"IoepFindErrThread");
00128
PERRTHREAD ErrThread =
NULL;
00129 PLIST_ENTRY list;
00130 KIRQL Irql;
00131
00132
ENTER(2, (
"(KeyType=%x,Key=%p)\n", KeyType,
Key));
00133
00134 ExAcquireSpinLock(&
IoepErrListLock, &Irql);
00135
for (list =
IoepErrThreadListHead.Flink;
00136 list != &
IoepErrThreadListHead;
00137 list = list->Flink)
00138 {
00139 ErrThread = CONTAINING_RECORD(list,
ERRTHREAD, list);
00140
if (ErrThread->
ThreadKeyType == KeyType)
00141 {
00142
switch (KeyType)
00143 {
00144
case THREADKEY_IRP:
00145
if ((
PIRP)
Key == ErrThread->
ThreadKey.IrpKey.Irp)
00146 {
00147
break;
00148 }
00149
else
00150 {
00151
PIO_STACK_LOCATION IrpSp;
00152
00153 IrpSp =
IoGetCurrentIrpStackLocation((
PIRP)
Key);
00154
if ((IrpSp->
MajorFunction ==
00155 ErrThread->
ThreadKey.IrpKey.MajorFunction) &&
00156 (IrpSp->
MinorFunction ==
00157 ErrThread->
ThreadKey.IrpKey.MinorFunction) &&
00158 RtlEqualMemory(&IrpSp->
Parameters.Others,
00159 ErrThread->
ThreadKey.IrpKey.Arguments,
00160
sizeof(PVOID)*4) &&
00161 (IopDbgGetLowestDevice(IrpSp->
DeviceObject) ==
00162 ErrThread->
ThreadKey.IrpKey.TargetDevice))
00163 {
00164
break;
00165 }
00166 }
00167
break;
00168
00169
case THREADKEY_THREADID:
00170
if ((
PKTHREAD)
Key == ErrThread->
ThreadKey.ThIDKey.ThreadID)
00171 {
00172
break;
00173 }
00174
break;
00175 }
00176 }
00177 ErrThread =
NULL;
00178 }
00179 ExReleaseSpinLock(&
IoepErrListLock, Irql);
00180
00181
EXIT(2, (
"=%p\n", ErrThread));
00182
return ErrThread;
00183 }
00184
00185
PERRTHREAD
00186 IoepNewErrThread(
00187 IN ULONG KeyType,
00188 IN PVOID Key
00189 )
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 {
00205
PROCNAME(
"IoepNewErrThread");
00206
PERRTHREAD ErrThread;
00207
00208
ENTER(2, (
"(KeyType=%x,Key=%p)\n", KeyType,
Key));
00209
00210 ErrThread =
ExAllocatePoolWithTag(
NonPagedPool,
00211
sizeof(
ERRTHREAD),
00212
IOETAG_ERRTHREAD);
00213
00214
if (ErrThread !=
NULL)
00215 {
00216
PIO_STACK_LOCATION IrpSp;
00217
00218 InitializeListHead(&ErrThread->
ErrLogListHead);
00219 ErrThread->
ThreadKeyType = KeyType;
00220
00221
switch (KeyType)
00222 {
00223
case THREADKEY_IRP:
00224 IrpSp =
IoGetCurrentIrpStackLocation((
PIRP)
Key);
00225 ErrThread->
ThreadKey.IrpKey.Irp = (
PIRP)
Key;
00226 ErrThread->
ThreadKey.IrpKey.MajorFunction =
00227 IrpSp->
MajorFunction;
00228 ErrThread->
ThreadKey.IrpKey.MinorFunction =
00229 IrpSp->
MinorFunction;
00230 RtlCopyMemory(ErrThread->
ThreadKey.IrpKey.Arguments,
00231 &IrpSp->
Parameters.Others,
00232
sizeof(PVOID)*4);
00233 ErrThread->
ThreadKey.IrpKey.TargetDevice =
00234 IopDbgGetLowestDevice(IrpSp->
DeviceObject);
00235
break;
00236
00237
case THREADKEY_THREADID:
00238 ErrThread->
ThreadKey.ThIDKey.ThreadID = (
PKTHREAD)
Key;
00239
break;
00240 }
00241
ExInterlockedInsertHeadList(&
IoepErrThreadListHead,
00242 &ErrThread->
list,
00243 &
IoepErrListLock);
00244 }
00245
else
00246 {
00247
DBGPRINT((
"failed to allocate error thread\n"));
00248 }
00249
00250
EXIT(2, (
"=%p\n", ErrThread));
00251
return ErrThread;
00252 }
00253
00254
VOID
00255 IoepLogErr(
00256 IN ULONG KeyType,
00257 IN PVOID Key,
00258 IN CONST GUID *ComponentGuid,
00259 IN ULONG ErrCode,
00260 IN PWSTR TextData OPTIONAL,
00261 IN ULONG DataBlkType,
00262 IN ULONG DataBlkLen OPTIONAL,
00263 IN PVOID DataBlock OPTIONAL,
00264 IN CONST GUID *MofGuid OPTIONAL
00265 )
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 {
00288
PROCNAME(
"IoepLogErr");
00289
PERRTHREAD ErrThread;
00290
00291
ASSERT(
Key !=
NULL);
00292
ASSERT(ComponentGuid !=
NULL);
00293
ASSERT((DataBlkType ==
IOEDATA_NONE) ||
00294 (DataBlkLen > 0) && (DataBlock !=
NULL));
00295
ASSERT(DataBlkType <=
IOEDATA_MAX);
00296
ENTER(2, (
"(KeyType=%x,Key=%p,pGuid=%p,ErrCode=%x,Text=%S,Type=%x,Len=%d,DataBlk=%p,MofGuid=%p)\n",
00297 KeyType,
Key, ComponentGuid, ErrCode, TextData? TextData:
L"",
00298 DataBlkType, DataBlkLen, DataBlock, MofGuid));
00299
00300 ErrThread =
IoepFindErrThread(KeyType,
Key);
00301
if (ErrThread !=
NULL)
00302 {
00303
PERRENTRY Err;
00304
00305
ASSERT(!IsListEmpty(&ErrThread->
ErrLogListHead));
00306 Err =
ExAllocatePoolWithTag(
NonPagedPool,
00307
sizeof(
ERRENTRY),
00308
IOETAG_ERRENTRY);
00309
00310
if (Err !=
NULL)
00311 {
00312 BOOLEAN fOK =
TRUE;
00313 PVOID Data =
NULL;
00314 PWSTR pwstr =
NULL;
00315
00316 RtlZeroMemory(Err,
sizeof(
ERRENTRY));
00317
if (DataBlkType !=
IOEDATA_NONE)
00318 {
00319 Data =
ExAllocatePoolWithTag(
NonPagedPool,
00320 DataBlkLen,
00321
IOETAG_DATABLOCK);
00322
00323
if (Data !=
NULL)
00324 {
00325 RtlCopyMemory(Data, DataBlock, DataBlkLen);
00326 }
00327
else
00328 {
00329 fOK =
FALSE;
00330
DBGPRINT((
"failed to allocate data block (len=%d)\n",
00331 DataBlkLen));
00332 }
00333 }
00334
else
00335 {
00336
00337
00338
00339 DataBlkLen = 0;
00340 }
00341
00342
if (TextData !=
NULL)
00343 {
00344 ULONG len;
00345
00346 len = wcslen(TextData)*
sizeof(WCHAR) +
sizeof(UNICODE_NULL);
00347 pwstr =
ExAllocatePoolWithTag(
NonPagedPool,
00348 len,
00349
IOETAG_DATATEXT);
00350
00351
if (pwstr !=
NULL)
00352 {
00353 RtlCopyMemory(pwstr, TextData, len);
00354
RtlInitUnicodeString(&Err->
unicodeStr, pwstr);
00355 }
00356
else
00357 {
00358 fOK =
FALSE;
00359
DBGPRINT((
"failed to allocate text data (len=%d)\n",
00360 len));
00361 }
00362 }
00363
00364
if (fOK)
00365 {
00366
PERRLOG ErrLog;
00367 KIRQL Irql;
00368
00369 Err->
ErrID.
ComponentGuid = *ComponentGuid;
00370 Err->
ErrID.
ErrCode = ErrCode;
00371 Err->
DataBlkType = DataBlkType;
00372 Err->
DataBlkLen = DataBlkLen;
00373 Err->
DataBlk = Data;
00374
if (MofGuid !=
NULL)
00375 {
00376 Err->
MofGuid = *MofGuid;
00377 }
00378
00379 ExAcquireSpinLock(&
IoepErrListLock, &Irql);
00380 ErrLog = CONTAINING_RECORD(ErrThread->
ErrLogListHead.Flink,
00381
ERRLOG,
00382 list);
00383 PushEntryList(&ErrLog->
ErrStack, &Err->
slist);
00384 ExReleaseSpinLock(&
IoepErrListLock, Irql);
00385 }
00386
else
00387 {
00388
if (Data !=
NULL)
00389 {
00390
ExFreePool(Data);
00391 }
00392
if (pwstr !=
NULL)
00393 {
00394
ExFreePool(pwstr);
00395 }
00396
ExFreePool(Err);
00397 }
00398 }
00399
else
00400 {
00401
DBGPRINT((
"failed to allocate error entry\n"));
00402 }
00403 }
00404
else
00405 {
00406
DBGPRINT((
"failed to find associated error thread (Type=%x,Key=%p)\n",
00407 KeyType,
Key));
00408 }
00409
00410
EXIT(2, (
"!\n"));
00411 }
00412
00413
VOID
00414 IoepFreeErrStack(
00415 IN
PERRENTRY ErrStack
00416 )
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 {
00430
PROCNAME(
"IoepFreeErrStack");
00431
PERRENTRY Err, ErrNext;
00432 KIRQL Irql;
00433
00434
ASSERT(ErrStack !=
NULL);
00435
ENTER(2, (
"(ErrStack=%p)\n", ErrStack));
00436
00437 ExAcquireSpinLock(&
IoepErrListLock, &Irql);
00438
for (Err = ErrStack; Err !=
NULL; Err = ErrNext)
00439 {
00440
if (Err->
DataBlk !=
NULL)
00441 {
00442
ExFreePool(Err->
DataBlk);
00443 Err->
DataBlk =
NULL;
00444 }
00445
RtlFreeUnicodeString(&Err->
unicodeStr);
00446 ErrNext =
IoepGetNextErrEntry(Err);
00447 Err->
slist.Next =
NULL;
00448
ExFreePool(Err);
00449 }
00450 ExReleaseSpinLock(&
IoepErrListLock, Irql);
00451
00452
EXIT(2, (
"!\n"));
00453 }
00454
00455
PERRMODULE
00456 IoepFindErrModule(
00457 IN CONST GUID *ComponentGuid
00458 )
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 {
00473
PROCNAME(
"IoepFindErrModule");
00474
PERRMODULE ErrModule =
NULL;
00475 PLIST_ENTRY list;
00476 KIRQL Irql;
00477
00478
ENTER(2, (
"(pGuid=%p)\n", ComponentGuid));
00479
00480 ExAcquireSpinLock(&
IoepErrListLock, &Irql);
00481
for (list =
IoepErrModuleListHead.Flink;
00482 list != &
IoepErrModuleListHead;
00483 list = list->Flink)
00484 {
00485 ErrModule = CONTAINING_RECORD(list,
ERRMODULE, list);
00486
if (RtlEqualMemory(&ErrModule->
ComponentGuid,
00487 ComponentGuid,
00488
sizeof(GUID)))
00489 {
00490
break;
00491 }
00492 ErrModule =
NULL;
00493 }
00494 ExReleaseSpinLock(&
IoepErrListLock, Irql);
00495
00496
EXIT(2, (
"=%p\n", ErrModule));
00497
return ErrModule;
00498 }
00499
00500
NTSTATUS
00501 IoepExtractErrData(
00502 IN
PERRENTRY ErrStack,
00503 OUT PVOID Buffer,
00504 IN ULONG BuffSize,
00505 OUT PULONG DataSize OPTIONAL
00506 )
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 {
00524
PROCNAME(
"IoepExtractErrData");
00525
NTSTATUS status;
00526
PERRENTRY Err;
00527 ULONG len, i;
00528
00529
ASSERT(ErrStack !=
NULL);
00530
ASSERT((
Buffer !=
NULL) && (BuffSize > 0) || (DataSize !=
NULL));
00531
ENTER(2, (
"(ErrStack=%p,Buff=%p,BuffSize=%d,pDataSize=%p)\n",
00532 ErrStack,
Buffer, BuffSize, DataSize));
00533
00534
for (Err = ErrStack, len =
sizeof(
ERRINFO) -
sizeof(
ERRDATA), i = 0;
00535 Err !=
NULL;
00536 Err =
IoepGetNextErrEntry(Err), i++)
00537 {
00538 len +=
sizeof(
ERRDATA) +
00539 Err->
DataBlkLen +
00540 Err->
unicodeStr.MaximumLength;
00541 }
00542
00543
if (len <= BuffSize)
00544 {
00545
if ((
Buffer !=
NULL) && (len > 0))
00546 {
00547
PERRINFO ErrInfo = (
PERRINFO)
Buffer;
00548 PUCHAR pBuff;
00549
00550 ErrInfo->
Signature =
SIG_ERRINFO;
00551 ErrInfo->
Version =
IOE_ERRINFO_VERSION;
00552 ErrInfo->
Size = len;
00553 ErrInfo->
DataTag =
NULL;
00554 ErrInfo->
TagFlags = 0;
00555 ErrInfo->
NumErrEntries = i;
00556 pBuff = (PUCHAR)ErrInfo +
sizeof(
ERRINFO) +
sizeof(
ERRDATA)*(i - 1);
00557
for (Err = ErrStack, i = 0;
00558 Err !=
NULL;
00559 Err =
IoepGetNextErrEntry(Err), i++)
00560 {
00561 ErrInfo->
ErrEntries[i].
ErrID = Err->
ErrID;
00562 ErrInfo->
ErrEntries[i].
DataBlkType = Err->
DataBlkType;
00563 ErrInfo->
ErrEntries[i].
DataBlkLen = Err->
DataBlkLen;
00564 ErrInfo->
ErrEntries[i].
MofGuid = Err->
MofGuid;
00565
00566
if (Err->
unicodeStr.MaximumLength > 0)
00567 {
00568 ErrInfo->
ErrEntries[i].
TextDataOffset = pBuff -
00569 (PUCHAR)ErrInfo;
00570 RtlCopyMemory(pBuff,
00571 Err->
unicodeStr.Buffer,
00572 Err->
unicodeStr.MaximumLength);
00573 pBuff += Err->
unicodeStr.MaximumLength;
00574 }
00575
else
00576 {
00577 ErrInfo->
ErrEntries[i].
TextDataOffset = 0;
00578 }
00579
00580
if (Err->
DataBlk !=
NULL)
00581 {
00582 ErrInfo->
ErrEntries[i].
DataBlkOffset = pBuff -
00583 (PUCHAR)ErrInfo;
00584 RtlCopyMemory(pBuff, Err->
DataBlk, Err->
DataBlkLen);
00585 pBuff += Err->
DataBlkLen;
00586 }
00587
else
00588 {
00589 ErrInfo->
ErrEntries[i].
DataBlkOffset = 0;
00590 }
00591 }
00592 }
00593
00594 status = STATUS_SUCCESS;
00595 }
00596
else
00597 {
00598 status = STATUS_BUFFER_TOO_SMALL;
00599
DBGPRINT((
"buffer too small (size=%d,need=%d)\n", BuffSize, len));
00600 }
00601
00602
if (DataSize !=
NULL)
00603 {
00604 *DataSize = len;
00605 }
00606
00607
EXIT(2, (
"=%x(len=%d)\n", status, len));
00608
return status;
00609 }
00610
00611
NTSTATUS
00612 IoepFireWMIEvent(
00613 IN
PERRINFO ErrInfo,
00614 IN PWSTR InstanceName
00615 )
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 {
00631
PROCNAME(
"IoepFireWMIEvent");
00632
NTSTATUS status;
00633
00634
ENTER(2, (
"(ErrInfo=%p,InstanceName=%S)\n", ErrInfo, InstanceName));
00635
00636
if (ErrInfo !=
NULL)
00637 {
00638 ULONG NameLen, EventSize;
00639 PWNODE_SINGLE_INSTANCE event;
00640
00641 NameLen = wcslen(InstanceName)*
sizeof(WCHAR) +
sizeof(UNICODE_NULL);
00642 EventSize =
sizeof(WNODE_SINGLE_INSTANCE) + NameLen + ErrInfo->Size;
00643 event =
ExAllocatePoolWithTag(
NonPagedPool,
00644 EventSize,
00645
IOETAG_WMIEVENT);
00646
if (event !=
NULL)
00647 {
00648 event->WnodeHeader.BufferSize = EventSize;
00649 event->WnodeHeader.ProviderId = 0;
00650 event->WnodeHeader.Guid =
IoepGuid;
00651 event->WnodeHeader.Flags = WNODE_FLAG_SINGLE_INSTANCE |
00652 WNODE_FLAG_EVENT_ITEM;
00653
KeQuerySystemTime(&event->WnodeHeader.TimeStamp);
00654 event->OffsetInstanceName =
sizeof(WNODE_SINGLE_INSTANCE);
00655 event->DataBlockOffset =
sizeof(WNODE_SINGLE_INSTANCE) + NameLen;
00656 event->SizeDataBlock = ErrInfo->Size;
00657 RtlCopyMemory(&event->VariableData, InstanceName, NameLen);
00658 RtlCopyMemory(event->VariableData + NameLen,
00659 ErrInfo,
00660 ErrInfo->Size);
00661 status =
IoWMIWriteEvent(event);
00662 }
00663
else
00664 {
00665 status = STATUS_INSUFFICIENT_RESOURCES;
00666
DBGPRINT((
"failed to allocate WMI event node (len=%d)\n",
00667 EventSize));
00668 }
00669 }
00670
else
00671 {
00672 status = STATUS_SUCCESS;
00673 }
00674
00675
EXIT(2, (
"=%x\n", status));
00676
return status;
00677 }
00678
00679
NTSTATUS
00680 IoepHandleErrCase(
00681 IN
PERRINFO ErrInfo,
00682 IN
PERRCASE ErrCase,
00683 IN ULONG Method,
00684 OUT PUNICODE_STRING unicodeMsg OPTIONAL
00685 )
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 {
00703
PROCNAME(
"IoepHandleErrCase");
00704
NTSTATUS status;
00705
PERRCASEDB ErrCaseDB;
00706
00707
PAGED_CODE();
00708
ENTER(2, (
"(ErrInfo=%p,ErrCase=%p,Method=%x,unicodeMsg=%p)\n",
00709 ErrInfo, ErrCase, Method, unicodeMsg));
00710
00711 ErrCaseDB =
IoepGetErrCaseDB();
00712
if (ErrCaseDB !=
NULL)
00713 {
00714
PMETHOD MethodTable;
00715 ULONG i;
00716 PVOID MethodData;
00717 UNICODE_STRING unicodeStr;
00718
PERRHANDLER ErrHandler;
00719 PWSTR MsgTemplate;
00720
00721 MethodTable = (
PMETHOD)((ULONG_PTR)ErrCaseDB +
00722 ErrCaseDB->
DataBlkOffset +
00723 ErrCase->MethodOffset);
00724
00725
for (i = 0, status = STATUS_NOT_FOUND;
00726 (status == STATUS_NOT_FOUND) && (i < ErrCase->NumMethods);
00727 ++i)
00728 {
00729
if ((Method !=
IOEMETHOD_ANY) &&
00730 (Method != MethodTable[i].
MethodType))
00731 {
00732
continue;
00733 }
00734
00735 MethodData = (PVOID)((ULONG_PTR)ErrCaseDB +
00736 ErrCaseDB->
DataBlkOffset +
00737 MethodTable[i].
MethodDataOffset);
00738
00739
switch (MethodTable[i].
MethodType)
00740 {
00741
case IOEMETHOD_LONGMSG:
00742 status =
IoepGetErrMessage((
PMSGDATA)MethodData,
00743 ErrInfo,
00744 unicodeMsg? unicodeMsg:
00745 &unicodeStr);
00746
00747
if (
NT_SUCCESS(status) && (unicodeMsg ==
NULL))
00748 {
00749
IoRaiseInformationalHardError(
STATUS_IOE_MESSAGE,
00750 &unicodeStr,
00751
NULL);
00752
RtlFreeUnicodeString(&unicodeStr);
00753 }
00754
break;
00755
00756
case IOEMETHOD_SHORTMSG:
00757 MsgTemplate =
00758 (PWSTR)((ULONG_PTR)ErrCaseDB +
00759 ErrCaseDB->
DataBlkOffset +
00760 ((
PMSGDATA)MethodData)->MsgTemplateOffset);
00761
00762
if (unicodeMsg ==
NULL)
00763 {
00764
RtlInitUnicodeString(&unicodeStr, MsgTemplate);
00765
IoRaiseInformationalHardError(
STATUS_IOE_MESSAGE,
00766 &unicodeStr,
00767
NULL);
00768 status = STATUS_SUCCESS;
00769 }
00770
else
00771 {
00772 ULONG len;
00773 PWSTR pwstr;
00774
00775 len = wcslen(MsgTemplate)*
sizeof(WCHAR) +
00776
sizeof(UNICODE_NULL);
00777 pwstr =
ExAllocatePoolWithTag(
PagedPool,
00778 len,
00779
IOETAG_DATAWSTR);
00780
if (pwstr !=
NULL)
00781 {
00782 RtlCopyMemory(pwstr, MsgTemplate, len);
00783
RtlInitUnicodeString(unicodeMsg, pwstr);
00784 status = STATUS_SUCCESS;
00785 }
00786
else
00787 {
00788 status = STATUS_INSUFFICIENT_RESOURCES;
00789
DBGPRINT((
"failed to allocate short message buffer (len=%d)\n",
00790 len));
00791 }
00792 }
00793
break;
00794
00795
case IOEMETHOD_HANDLER:
00796 ErrHandler =
IoepFindErrHandler(
00797 &((
PHANDLERDATA)MethodData)->ComponentGuid,
00798 ((
PHANDLERDATA)MethodData)->HandlerIndex);
00799
00800
if (ErrHandler !=
NULL)
00801 {
00802 status = ErrHandler(ErrInfo,
00803 ((
PHANDLERDATA)MethodData)->Param);
00804 }
00805
break;
00806
00807
default:
00808
DBGPRINT((
"invalid method type %d\n",
00809 MethodTable[i].MethodType));
00810 }
00811 }
00812 }
00813
else
00814 {
00815 status =
STATUS_IOE_DATABASE_NOT_READY;
00816
DBGPRINT((
"error case database not ready\n"));
00817 }
00818
00819
EXIT(2, (
"=%x\n", status));
00820
return status;
00821 }
00822
00823
PERRHANDLER
00824 IoepFindErrHandler(
00825 IN CONST GUID *ComponentGuid,
00826 IN ULONG HandlerIndex
00827 )
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 {
00844
PROCNAME(
"IoepFindErrHandler");
00845
PERRHANDLER ErrHandler =
NULL;
00846
PERRMODULE ErrModule;
00847
00848
ENTER(2, (
"(pGuid=%p,Index=%x)\n", ComponentGuid, HandlerIndex));
00849
00850 ErrModule =
IoepFindErrModule(ComponentGuid);
00851
00852
if ((ErrModule !=
NULL) && (HandlerIndex < ErrModule->
NumErrHandlers))
00853 {
00854 ErrHandler = ErrModule->
HandlerTable[HandlerIndex];
00855 }
00856
00857
EXIT(2, (
"=%p\n", ErrHandler));
00858
return ErrHandler;
00859 }
00860
00861 BOOLEAN
00862 IoepMatchErrIDPath(
00863 IN
PERRINFO ErrInfo,
00864 IN
PERRID ErrIDPath,
00865 IN ULONG NumErrIDs
00866 )
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 {
00883
PROCNAME(
"IoepMatchErrIDPath");
00884 BOOLEAN rc =
TRUE;
00885 BOOLEAN fWildCard =
FALSE;
00886 ULONG i, j;
00887
00888
PAGED_CODE();
00889
ENTER(2, (
"(ErrInfo=%p,pErrID=%p,NumIDs=%d)\n",
00890 ErrInfo, ErrIDPath, NumErrIDs));
00891
00892
for (i = j = 0; (i < NumErrIDs) && (j < ErrInfo->NumErrEntries);)
00893 {
00894
if (ErrIDPath[i].ErrCode == 0)
00895 {
00896 fWildCard =
TRUE;
00897 i++;
00898 }
00899
else if (RtlEqualMemory(&ErrIDPath[i].ComponentGuid,
00900 &ErrInfo->ErrEntries[j].ErrID.ComponentGuid,
00901
sizeof(GUID)) &&
00902 (ErrIDPath[i].ErrCode == ErrInfo->ErrEntries[j].ErrID.ErrCode))
00903 {
00904 i++;
00905 j++;
00906 fWildCard =
FALSE;
00907 }
00908
else if (fWildCard)
00909 {
00910 j++;
00911 }
00912
else
00913 {
00914 rc =
FALSE;
00915
break;
00916 }
00917 }
00918
00919
if ((rc ==
TRUE) && (i < NumErrIDs))
00920 {
00921
00922
00923
00924
00925
00926
00927
00928 rc =
FALSE;
00929 }
00930
00931
EXIT(2, (
"=%x\n", rc));
00932
return rc;
00933 }
00934
00935
NTSTATUS
00936 IoepGetErrMessage(
00937 IN
PMSGDATA MsgData,
00938 IN
PERRINFO ErrInfo,
00939 OUT PUNICODE_STRING unicodeMsg
00940 )
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961 {
00962
PROCNAME(
"IoepGetErrMessage");
00963
NTSTATUS status = STATUS_SUCCESS;
00964
PERRCASEDB ErrCaseDB;
00965
00966
PAGED_CODE();
00967
ENTER(2, (
"(pMsgData=%p,ErrInfo=%p,pMsg=%p)\n",
00968 MsgData, ErrInfo, unicodeMsg));
00969
00970 ErrCaseDB =
IoepGetErrCaseDB();
00971
if (ErrCaseDB !=
NULL)
00972 {
00973 PWSTR MsgTemplate, MsgBuff, pwstr;
00974
00975 MsgTemplate = (PWSTR)((ULONG_PTR)ErrCaseDB +
00976 ErrCaseDB->
DataBlkOffset +
00977 MsgData->MsgTemplateOffset);
00978
00979 MsgBuff =
ExAllocatePoolWithTag(
PagedPool,
00980
sizeof(WCHAR)*
MAX_MSG_LEN +
00981
sizeof(UNICODE_NULL),
00982
IOETAG_MSGBUFF);
00983
00984
if (MsgBuff !=
NULL)
00985 {
00986 MsgBuff[0] =
L'\0';
00987
RtlInitUnicodeString(unicodeMsg, MsgBuff);
00988 unicodeMsg->MaximumLength =
sizeof(WCHAR)*
MAX_MSG_LEN +
00989
sizeof(UNICODE_NULL);
00990
00991
while (
NT_SUCCESS(status))
00992 {
00993 pwstr = wcschr(MsgTemplate,
L'%');
00994
if (pwstr ==
NULL)
00995 {
00996 status =
RtlAppendUnicodeToString(unicodeMsg, MsgTemplate);
00997
if (!
NT_SUCCESS(status))
00998 {
00999
DBGPRINT((
"failed to append unicode string (rc=%x)\n",
01000 status));
01001 }
01002
break;
01003 }
01004
else if ((pwstr[1] >=
L'0') && (pwstr[1] <=
L'9'))
01005 {
01006 ULONG ArgIndex;
01007 PWSTR pwstr2;
01008
01009 ArgIndex = wcstoul(&pwstr[1], &pwstr2, 10);
01010 status =
IoepUnicodeStringCatN(unicodeMsg,
01011 MsgTemplate,
01012 pwstr - MsgTemplate);
01013
if (
NT_SUCCESS(status))
01014 {
01015 MsgTemplate = pwstr2;
01016 status =
IoepCatMsgArg(unicodeMsg,
01017 &MsgData->Args[ArgIndex],
01018 ErrInfo);
01019 }
01020 }
01021
else
01022 {
01023 pwstr++;
01024 status =
IoepUnicodeStringCatN(unicodeMsg,
01025 MsgTemplate,
01026 pwstr - MsgTemplate);
01027
if (
NT_SUCCESS(status))
01028 {
01029 MsgTemplate = pwstr;
01030 }
01031 }
01032 }
01033 }
01034
else
01035 {
01036 status = STATUS_INSUFFICIENT_RESOURCES;
01037
DBGPRINT((
"failed to allocate message buffer\n"));
01038 }
01039 }
01040
else
01041 {
01042 status =
STATUS_IOE_DATABASE_NOT_READY;
01043
DBGPRINT((
"error case database not ready\n"));
01044 }
01045
01046
EXIT(2, (
"=%x(Msg=%S)\n",
01047 status, unicodeMsg->Buffer? unicodeMsg->Buffer:
L""));
01048
return status;
01049 }
01050
01051
NTSTATUS
01052 IoepCatMsgArg(
01053 IN OUT PUNICODE_STRING unicodeMsg,
01054 IN
PMSGARG MsgArg,
01055 IN
PERRINFO ErrInfo
01056 )
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 {
01075
PROCNAME(
"IoepCatMsgArg");
01076
NTSTATUS status = STATUS_SUCCESS;
01077
PERRCASEDB ErrCaseDB;
01078
01079
PAGED_CODE();
01080
ENTER(2, (
"(Msg=%S,pMsgArg=%p,ErrInfo=%p)\n",
01081 unicodeMsg->Buffer, MsgArg, ErrInfo));
01082
01083 ErrCaseDB =
IoepGetErrCaseDB();
01084
if (ErrCaseDB !=
NULL)
01085 {
01086
if (MsgArg->ErrIDIndex < ErrInfo->NumErrEntries)
01087 {
01088
PERRDATA ErrData;
01089 ANSI_STRING ansiStr;
01090 UNICODE_STRING unicodeStr;
01091
PHANDLERDATA HandlerData;
01092
PERRHANDLER ErrHandler;
01093
01094 ErrData = &ErrInfo->ErrEntries[MsgArg->ErrIDIndex];
01095
switch (MsgArg->ArgType)
01096 {
01097
case IOEDATA_TEXT:
01098 status =
RtlAppendUnicodeToString(
01099 unicodeMsg,
01100 (PWSTR)((PUCHAR)ErrInfo +
01101 ErrData->
TextDataOffset));
01102
if (!
NT_SUCCESS(status))
01103 {
01104
DBGPRINT((
"failed to append unicode string (rc=%x)\n",
01105 status));
01106 }
01107
break;
01108
01109
case IOEDATA_WSTRING:
01110 status =
RtlAppendUnicodeToString(
01111 unicodeMsg,
01112 (PWSTR)((PUCHAR)ErrInfo +
01113 ErrData->
DataBlkOffset));
01114
if (!
NT_SUCCESS(status))
01115 {
01116
DBGPRINT((
"failed to append unicode string argument (rc=%x)\n",
01117 status));
01118 }
01119
break;
01120
01121
case IOEDATA_PRIVATE:
01122 HandlerData = (
PHANDLERDATA)((ULONG_PTR)ErrCaseDB +
01123 ErrCaseDB->
DataBlkOffset +
01124 MsgArg->ArgDataOffset);
01125 ErrHandler =
IoepFindErrHandler(&HandlerData->
ComponentGuid,
01126 HandlerData->
HandlerIndex);
01127
if (ErrHandler !=
NULL)
01128 {
01129 status = ErrHandler(ErrData, HandlerData->
Param);
01130 }
01131
break;
01132
01133
default:
01134
DBGPRINT((
"invalid message argument type %d\n",
01135 MsgArg->ArgType));
01136 }
01137 }
01138
else
01139 {
01140 status = STATUS_UNSUCCESSFUL;
01141
DBGPRINT((
"failed to find error entry\n"));
01142 }
01143 }
01144
else
01145 {
01146 status =
STATUS_IOE_DATABASE_NOT_READY;
01147
DBGPRINT((
"error case database not ready\n"));
01148 }
01149
01150
EXIT(2, (
"=%x(Msg=%S)\n", status, unicodeMsg->Buffer));
01151
return status;
01152 }
01153
01154
NTSTATUS
01155 IoepUnicodeStringCatN(
01156 IN OUT PUNICODE_STRING unicodeStr,
01157 IN PWSTR pwstr,
01158 IN ULONG len
01159 )
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 {
01177
PROCNAME(
"IoepUnicodeStringCatN");
01178
NTSTATUS status = STATUS_SUCCESS;
01179
01180
PAGED_CODE();
01181
ENTER(2, (
"(Msg=%S,Str=%S,Len=%d)\n", unicodeStr->Buffer, pwstr, len));
01182
01183
if (len < (ULONG)(unicodeStr->MaximumLength - unicodeStr->Length))
01184 {
01185 wcsncpy(unicodeStr->Buffer, pwstr, len/
sizeof(WCHAR));
01186 unicodeStr->Length += (
USHORT)len;
01187 unicodeStr->Buffer[len/
sizeof(WCHAR)] =
L'\0';
01188 }
01189
else
01190 {
01191 status = STATUS_BUFFER_TOO_SMALL;
01192
DBGPRINT((
"unicode string too small\n"));
01193 }
01194
01195
EXIT(2, (
"=%x(Msg=%S)\n", status, unicodeStr->Buffer));
01196
return status;
01197 }
01198
01199
PERRCASEDB
01200 IoepGetErrCaseDB(
01201 VOID
01202 )
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 {
01219
PROCNAME(
"IoepGetErrCaseDB");
01220
01221
PAGED_CODE();
01222
ENTER(2, (
"()\n"));
01223
01224
if (
IoepErrCaseDB ==
NULL)
01225 {
01226 OBJECT_ATTRIBUTES ObjAttr;
01227
NTSTATUS status;
01228 HANDLE hReg, hFile;
01229
01230 InitializeObjectAttributes(&ObjAttr,
01231 &
IoepRegKeyStrIoErr,
01232 OBJ_CASE_INSENSITIVE,
01233
NULL,
01234
NULL);
01235 status = ZwOpenKey(&hReg, KEY_READ, &ObjAttr);
01236
if (
NT_SUCCESS(status))
01237 {
01238 PKEY_VALUE_FULL_INFORMATION KeyValue;
01239
01240 status =
IopGetRegistryValue(hReg,
L"ErrCaseDB", &KeyValue);
01241
if (
NT_SUCCESS(status))
01242 {
01243 UNICODE_STRING unicodeStr;
01244 IO_STATUS_BLOCK IoStatusBlk;
01245
01246
RtlInitUnicodeString(&unicodeStr,
01247 (PWSTR)((PUCHAR)KeyValue +
01248 KeyValue->DataOffset));
01249 InitializeObjectAttributes(&ObjAttr,
01250 &unicodeStr,
01251 OBJ_CASE_INSENSITIVE,
01252
NULL,
01253
NULL);
01254 status =
ZwCreateFile(&hFile,
01255 FILE_READ_DATA,
01256 &ObjAttr,
01257 &IoStatusBlk,
01258
NULL,
01259 FILE_ATTRIBUTE_NORMAL,
01260 FILE_SHARE_READ,
01261 FILE_OPEN,
01262 FILE_NON_DIRECTORY_FILE |
01263 FILE_SEQUENTIAL_ONLY |
01264 FILE_SYNCHRONOUS_IO_NONALERT,
01265
NULL,
01266 0);
01267
01268
if (
NT_SUCCESS(status) &&
01269 (IoStatusBlk.Information == FILE_OPENED))
01270 {
01271
ERRCASEDB DBHeader;
01272
01273 status = ZwReadFile(hFile,
01274
NULL,
01275
NULL,
01276
NULL,
01277 &IoStatusBlk,
01278 &DBHeader,
01279
sizeof(DBHeader),
01280
NULL,
01281
NULL);
01282
01283
if (
NT_SUCCESS(status))
01284 {
01285
IoepErrCaseDB =
ExAllocatePoolWithTag(
PagedPool,
01286 DBHeader.Length,
01287
IOETAG_ERRCASEDB);
01288
if (
IoepErrCaseDB !=
NULL)
01289 {
01290 RtlCopyMemory(
IoepErrCaseDB,
01291 &DBHeader,
01292
sizeof(DBHeader));
01293 status = ZwReadFile(hFile,
01294
NULL,
01295
NULL,
01296
NULL,
01297 &IoStatusBlk,
01298 (PUCHAR)
IoepErrCaseDB +
01299
sizeof(DBHeader),
01300 DBHeader.
Length -
01301
sizeof(DBHeader),
01302
NULL,
01303
NULL);
01304
01305
if (!
NT_SUCCESS(status))
01306 {
01307
ExFreePool(
IoepErrCaseDB);
01308
IoepErrCaseDB =
NULL;
01309
DBGPRINT((
"failed to read error case database (rc=%x)\n",
01310 status));
01311 }
01312 }
01313
else
01314 {
01315
DBGPRINT((
"failed to allocate storage for error case database (len=%d)\n",
01316 DBHeader.Length));
01317 }
01318 }
01319
else
01320 {
01321
DBGPRINT((
"failed to read database header (rc=%x)\n",
01322 status));
01323 }
01324 ZwClose(hFile);
01325 }
01326
else
01327 {
01328
DBGPRINT((
"failed to open error case database (rc=%x)\n",
01329 status));
01330 }
01331
ExFreePool(KeyValue);
01332 }
01333
else
01334 {
01335
DBGPRINT((
"failed to read registry value (rc=%x)\n", status));
01336 }
01337 ZwClose(hReg);
01338 }
01339
else
01340 {
01341
DBGPRINT((
"failed to open registry key (rc=%x)\n", status));
01342 }
01343 }
01344
01345
EXIT(2, (
"=%p\n",
IoepErrCaseDB));
01346
return IoepErrCaseDB;
01347 }