OSDN Git Service

fix ticket #18663
[yamy/yamy.git] / d / log.c
1 #if DBG\r
2 \r
3 #include <ntddk.h>\r
4 #include <stdarg.h>\r
5 \r
6 #include "log.h"\r
7 \r
8 #define BUF_MAX_SIZE 128\r
9 \r
10 typedef struct _logEntry {\r
11         LIST_ENTRY listEntry;\r
12         UNICODE_STRING log;\r
13 } logEntry;\r
14 \r
15 static LIST_ENTRY s_logList;\r
16 static KSPIN_LOCK s_logListLock;\r
17 static PIRP s_irp;\r
18 \r
19 void mayuLogInit(const char *message)\r
20 {\r
21         InitializeListHead(&s_logList);\r
22         KeInitializeSpinLock(&s_logListLock);\r
23         s_irp = NULL;\r
24         mayuLogEnque(message);\r
25 }\r
26 \r
27 void mayuLogTerm()\r
28 {\r
29         if (s_irp) {\r
30                 IoReleaseCancelSpinLock(s_irp->CancelIrql);\r
31                 s_irp->IoStatus.Status = STATUS_CANCELLED;\r
32                 s_irp->IoStatus.Information = 0;\r
33                 IoCompleteRequest(s_irp, IO_NO_INCREMENT);\r
34                 s_irp = NULL;\r
35         }\r
36 }\r
37 \r
38 void mayuLogEnque(const char *fmt, ...)\r
39 {\r
40         va_list argp;\r
41         logEntry *entry;\r
42         ANSI_STRING ansiBuf;\r
43         UNICODE_STRING unicodeBuf;\r
44         CHAR buf[BUF_MAX_SIZE] = "";\r
45         WCHAR wbuf[BUF_MAX_SIZE] = L"";\r
46         USHORT i, j;\r
47         ULONG ul;\r
48         PUNICODE_STRING punicode;\r
49 \r
50         entry = (logEntry*)ExAllocatePool(NonPagedPool, sizeof(logEntry));\r
51         if (!entry)\r
52                 return;\r
53         entry->log.Length = 0;\r
54         entry->log.MaximumLength = BUF_MAX_SIZE;\r
55         entry->log.Buffer = (PWSTR)ExAllocatePool(NonPagedPool, BUF_MAX_SIZE);\r
56 \r
57         unicodeBuf.Length = 0;\r
58         unicodeBuf.MaximumLength = BUF_MAX_SIZE;\r
59         unicodeBuf.Buffer = wbuf;\r
60 \r
61         ansiBuf.Length = 0;\r
62         ansiBuf.MaximumLength = BUF_MAX_SIZE;\r
63         ansiBuf.Buffer = buf;\r
64 \r
65         va_start(argp, fmt);\r
66         for (i = j = 0; i < BUF_MAX_SIZE; ++i) {\r
67                 ansiBuf.Buffer[i - j] = fmt[i];\r
68                 if (fmt[i] == '\0') {\r
69                         ansiBuf.Length = i - j;\r
70                         RtlAnsiStringToUnicodeString(&unicodeBuf, &ansiBuf, FALSE);\r
71                         RtlAppendUnicodeStringToString(&entry->log, &unicodeBuf);\r
72                         break;\r
73                 }\r
74                 if (fmt[i] == '%') {\r
75                         ansiBuf.Length = i - j;\r
76                         RtlAnsiStringToUnicodeString(&unicodeBuf, &ansiBuf, FALSE);\r
77                         RtlAppendUnicodeStringToString(&entry->log, &unicodeBuf);\r
78                         switch (fmt[++i]) {\r
79                         case 'x':\r
80                                 ul = va_arg(argp, ULONG);\r
81                                 RtlIntegerToUnicodeString(ul, 16, &unicodeBuf);\r
82                                 RtlAppendUnicodeStringToString(&entry->log, &unicodeBuf);\r
83                                 break;\r
84                         case 'd':\r
85                                 ul = va_arg(argp, ULONG);\r
86                                 RtlIntegerToUnicodeString(ul, 10, &unicodeBuf);\r
87                                 RtlAppendUnicodeStringToString(&entry->log, &unicodeBuf);\r
88                                 break;\r
89                         case 'T':\r
90                                 punicode = va_arg(argp, PUNICODE_STRING);\r
91                                 RtlAppendUnicodeStringToString(&entry->log, punicode);\r
92                         }\r
93                         j = i + 1;\r
94                 }\r
95         }\r
96         va_end(argp);\r
97 \r
98         ExInterlockedInsertTailList(&s_logList, &entry->listEntry, &s_logListLock);\r
99 \r
100         if (s_irp) {\r
101                 KIRQL cancelIrql;\r
102 \r
103                 mayuLogDeque(s_irp);\r
104                 IoAcquireCancelSpinLock(&cancelIrql);\r
105                 IoSetCancelRoutine(s_irp, NULL);\r
106                 IoReleaseCancelSpinLock(cancelIrql);\r
107                 IoCompleteRequest(s_irp, IO_NO_INCREMENT);\r
108                 s_irp = NULL;\r
109         }\r
110 }\r
111 \r
112 VOID mayuLogCancel(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)\r
113 {\r
114         s_irp = NULL;\r
115         IoReleaseCancelSpinLock(irp->CancelIrql);\r
116         irp->IoStatus.Status = STATUS_CANCELLED;\r
117         irp->IoStatus.Information = 0;\r
118         IoCompleteRequest(irp, IO_NO_INCREMENT);\r
119 }\r
120 \r
121 NTSTATUS mayuLogDeque(PIRP irp)\r
122 {\r
123         KIRQL currentIrql;\r
124 \r
125         KeAcquireSpinLock(&s_logListLock, &currentIrql);\r
126         if (IsListEmpty(&s_logList) == TRUE) {\r
127                 KIRQL cancelIrql;\r
128 \r
129                 IoAcquireCancelSpinLock(&cancelIrql);\r
130                 IoMarkIrpPending(irp);\r
131                 s_irp = irp;\r
132                 IoSetCancelRoutine(irp, mayuLogCancel);\r
133                 IoReleaseCancelSpinLock(cancelIrql);\r
134                 KeReleaseSpinLock(&s_logListLock, currentIrql);\r
135                 irp->IoStatus.Information = 0;\r
136                 irp->IoStatus.Status = STATUS_PENDING;\r
137         } else {\r
138                 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);\r
139                 PLIST_ENTRY pListEntry;\r
140                 logEntry *pEntry;\r
141 \r
142                 KeReleaseSpinLock(&s_logListLock, currentIrql);\r
143                 pListEntry = ExInterlockedRemoveHeadList(&s_logList, &s_logListLock);\r
144                 pEntry = CONTAINING_RECORD(pListEntry, logEntry, listEntry);\r
145                 RtlCopyMemory(irp->AssociatedIrp.SystemBuffer,\r
146                                           pEntry->log.Buffer, pEntry->log.Length);\r
147                 irp->IoStatus.Information = pEntry->log.Length;\r
148                 irp->IoStatus.Status = STATUS_SUCCESS;\r
149                 ExFreePool(pEntry->log.Buffer);\r
150                 ExFreePool(pEntry);\r
151         }\r
152         return irp->IoStatus.Status;\r
153 }\r
154 \r
155 #endif // DBG\r