sync with trunk r46493
[reactos.git] / drivers / network / ndis / ndis / misc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/misc.c
5 */
6
7 #include "ndissys.h"
8
9 extern LONG CancelId;
10
11 /*
12 * @implemented
13 */
14 #undef NdisInterlockedAddUlong
15 VOID
16 EXPORT
17 NdisInterlockedAddUlong (
18 IN PULONG Addend,
19 IN ULONG Increment,
20 IN PNDIS_SPIN_LOCK SpinLock)
21 {
22 ExInterlockedAddUlong ( Addend, Increment, &SpinLock->SpinLock );
23 }
24
25 /*
26 * @implemented
27 */
28 VOID
29 EXPORT
30 NdisInterlockedAddLargeInteger(
31 IN PLARGE_INTEGER Addend,
32 IN LARGE_INTEGER Increment,
33 IN PNDIS_SPIN_LOCK SpinLock)
34 {
35 /* This needs to be verified. The documentation
36 * seems to be missing but it is exported by
37 * NDIS 5.1 so I'm implementing it like the other
38 * interlocked routines
39 */
40
41 ExInterlockedAddLargeInteger(Addend, Increment, &SpinLock->SpinLock);
42 }
43
44 /*
45 * @implemented
46 */
47 LONG
48 EXPORT
49 NdisCompareAnsiString(
50 IN PNDIS_ANSI_STRING String1,
51 IN PNDIS_ANSI_STRING String2,
52 BOOLEAN CaseInSensitive)
53 {
54 /* This one needs to be verified also. See the
55 * comment in NdisInterlockedAddLargeInteger
56 */
57
58 return RtlCompareString(String1, String2, CaseInSensitive);
59 }
60
61 /*
62 * @implemented
63 */
64 LONG
65 EXPORT
66 NdisCompareUnicodeString(
67 IN PNDIS_STRING String1,
68 IN PNDIS_STRING String2,
69 IN BOOLEAN CaseInSensitive)
70 {
71 /* This one needs to be verified also. See the
72 * comment in NdisInterlockedAddLargeInteger
73 */
74
75 return RtlCompareUnicodeString(String1, String2, CaseInSensitive);
76 }
77
78 /*
79 * @implemented
80 */
81 #undef NdisInterlockedInsertHeadList
82 PLIST_ENTRY
83 EXPORT
84 NdisInterlockedInsertHeadList(
85 IN PLIST_ENTRY ListHead,
86 IN PLIST_ENTRY ListEntry,
87 IN PNDIS_SPIN_LOCK SpinLock)
88 {
89 return ExInterlockedInsertHeadList ( ListHead, ListEntry, &SpinLock->SpinLock );
90 }
91
92 /*
93 * @implemented
94 */
95 #undef NdisInterlockedInsertTailList
96 PLIST_ENTRY
97 EXPORT
98 NdisInterlockedInsertTailList(
99 IN PLIST_ENTRY ListHead,
100 IN PLIST_ENTRY ListEntry,
101 IN PNDIS_SPIN_LOCK SpinLock)
102 {
103 return ExInterlockedInsertTailList ( ListHead, ListEntry, &SpinLock->SpinLock );
104 }
105
106
107 /*
108 * @implemented
109 */
110 #undef NdisInterlockedRemoveHeadList
111 PLIST_ENTRY
112 EXPORT
113 NdisInterlockedRemoveHeadList(
114 IN PLIST_ENTRY ListHead,
115 IN PNDIS_SPIN_LOCK SpinLock)
116 {
117 return ExInterlockedRemoveHeadList ( ListHead, &SpinLock->SpinLock );
118 }
119
120 typedef struct _NDIS_HANDLE_OBJECT
121 {
122 HANDLE FileHandle;
123 BOOLEAN Mapped;
124 ULONG FileLength;
125 PVOID MapBuffer;
126 } NDIS_HANDLE_OBJECT, *PNDIS_HANDLE_OBJECT;
127
128 __inline
129 PNDIS_HANDLE_OBJECT
130 NDIS_HANDLE_TO_POBJECT ( NDIS_HANDLE handle )
131 {
132 return (PNDIS_HANDLE_OBJECT)handle;
133 }
134
135 __inline
136 NDIS_HANDLE
137 NDIS_POBJECT_TO_HANDLE ( PNDIS_HANDLE_OBJECT obj )
138 {
139 return (NDIS_HANDLE)obj;
140 }
141
142 const WCHAR* NDIS_FILE_FOLDER = L"\\SystemRoot\\System32\\Drivers\\";
143
144 /*
145 * @implemented
146 */
147 VOID
148 EXPORT
149 NdisMapFile(
150 OUT PNDIS_STATUS Status,
151 OUT PVOID *MappedBuffer,
152 IN NDIS_HANDLE FileHandle)
153 {
154 PNDIS_HANDLE_OBJECT HandleObject = (PNDIS_HANDLE_OBJECT) FileHandle;
155
156 NDIS_DbgPrint(MAX_TRACE, ("called: FileHandle 0x%x\n", FileHandle));
157
158 if (HandleObject->Mapped)
159 {
160 /* If a file already mapped we will return an error code */
161 NDIS_DbgPrint(MIN_TRACE, ("File already mapped\n"));
162 *Status = NDIS_STATUS_ALREADY_MAPPED;
163 return;
164 }
165
166 HandleObject->Mapped = TRUE;
167 *MappedBuffer = HandleObject->MapBuffer;
168
169 /* Set returned status */
170 *Status = STATUS_SUCCESS;
171 }
172
173 /*
174 * @implemented
175 */
176 VOID
177 EXPORT
178 NdisUnmapFile(
179 IN NDIS_HANDLE FileHandle)
180 {
181 PNDIS_HANDLE_OBJECT HandleObject = (PNDIS_HANDLE_OBJECT) FileHandle;
182
183 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
184
185 HandleObject->Mapped = FALSE;
186 }
187
188 /*
189 * @implemented
190 */
191 VOID
192 EXPORT
193 NdisCloseFile(
194 IN NDIS_HANDLE FileHandle)
195 {
196 PNDIS_HANDLE_OBJECT FileHandleObject;
197
198 ASSERT_IRQL(PASSIVE_LEVEL);
199
200 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
201
202 ASSERT ( FileHandle );
203
204 FileHandleObject = NDIS_HANDLE_TO_POBJECT(FileHandle);
205
206 ASSERT ( FileHandleObject->FileHandle );
207
208 if ( FileHandleObject->Mapped )
209 NdisUnmapFile ( FileHandle );
210
211 ZwClose ( FileHandleObject->FileHandle );
212
213 memset ( FileHandleObject, 0, sizeof(NDIS_HANDLE_OBJECT) );
214
215 ExFreePool ( FileHandleObject );
216 }
217
218
219 /*
220 * @implemented
221 */
222 VOID
223 EXPORT
224 NdisOpenFile(
225 OUT PNDIS_STATUS Status,
226 OUT PNDIS_HANDLE FileHandle,
227 OUT PUINT FileLength,
228 IN PNDIS_STRING FileName,
229 IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress)
230 {
231 NDIS_STRING FullFileName;
232 OBJECT_ATTRIBUTES ObjectAttributes;
233 PNDIS_HANDLE_OBJECT FileHandleObject = NULL;
234 IO_STATUS_BLOCK IoStatusBlock;
235
236 ASSERT_IRQL(PASSIVE_LEVEL);
237
238 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
239
240 ASSERT ( Status && FileName );
241
242 *Status = NDIS_STATUS_SUCCESS;
243 FullFileName.Buffer = NULL;
244
245 FullFileName.Length = sizeof(NDIS_FILE_FOLDER);
246 FullFileName.MaximumLength = FileName->MaximumLength + sizeof(NDIS_FILE_FOLDER);
247 FullFileName.Buffer = ExAllocatePool ( NonPagedPool, FullFileName.MaximumLength );
248
249 if ( !FullFileName.Buffer )
250 {
251 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
252 *Status = NDIS_STATUS_RESOURCES;
253 goto cleanup;
254 }
255
256 FileHandleObject = ExAllocatePool ( NonPagedPool, sizeof(NDIS_HANDLE_OBJECT) );
257 if ( !FileHandleObject )
258 {
259 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
260 *Status = NDIS_STATUS_RESOURCES;
261 goto cleanup;
262 }
263 memset ( FileHandleObject, 0, sizeof(NDIS_HANDLE_OBJECT) );
264
265 memmove ( FullFileName.Buffer, NDIS_FILE_FOLDER, FullFileName.Length );
266 *Status = RtlAppendUnicodeStringToString ( &FullFileName, FileName );
267 if ( !NT_SUCCESS(*Status) )
268 {
269 NDIS_DbgPrint(MIN_TRACE, ("RtlAppendUnicodeStringToString failed (%x)\n", *Status));
270 *Status = NDIS_STATUS_FAILURE;
271 goto cleanup;
272 }
273
274 InitializeObjectAttributes ( &ObjectAttributes,
275 &FullFileName,
276 OBJ_CASE_INSENSITIVE,
277 NULL,
278 NULL );
279
280 *Status = ZwCreateFile (
281 &FileHandleObject->FileHandle,
282 FILE_READ_DATA|SYNCHRONIZE,
283 &ObjectAttributes,
284 &IoStatusBlock,
285 NULL, // PLARGE_INTEGER AllocationSize
286 0, // ULONG FileAttributes
287 FILE_SHARE_READ, // ULONG ShareAccess
288 FILE_CREATE, // ULONG CreateDisposition
289 FILE_SYNCHRONOUS_IO_NONALERT, // ULONG CreateOptions
290 0, // PVOID EaBuffer
291 0 ); // ULONG EaLength
292
293 if ( !NT_SUCCESS(*Status) )
294 {
295 NDIS_DbgPrint(MIN_TRACE, ("ZwCreateFile failed (%x)\n", *Status));
296 *Status = NDIS_STATUS_FAILURE;
297 }
298
299 cleanup:
300 if ( FullFileName.Buffer != NULL )
301 {
302 ExFreePool ( FullFileName.Buffer );
303 FullFileName.Buffer = NULL;
304 }
305 if ( !NT_SUCCESS(*Status) )
306 {
307 if( FileHandleObject ) {
308 ExFreePool ( FileHandleObject );
309 FileHandleObject = NULL;
310 }
311 *FileHandle = NULL;
312 }
313 else
314 *FileHandle = NDIS_POBJECT_TO_HANDLE(FileHandleObject);
315
316 return;
317 }
318
319 /*
320 * @implemented
321 */
322 CCHAR
323 EXPORT
324 NdisSystemProcessorCount(
325 VOID)
326 {
327 return (CCHAR)KeNumberProcessors;
328 }
329
330
331 /*
332 * @implemented
333 */
334 VOID
335 EXPORT
336 NdisGetCurrentProcessorCounts(
337 OUT PULONG pIdleCount,
338 OUT PULONG pKernelAndUser,
339 OUT PULONG pIndex)
340 /*
341 * FUNCTION:
342 * ARGUMENTS:
343 * NOTES:
344 * NDIS 5.0
345 */
346 {
347 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
348
349 ExGetCurrentProcessorCounts( (PULONG) pIdleCount, (PULONG) pKernelAndUser, (PULONG) pIndex);
350 }
351
352
353 /*
354 * @implemented
355 */
356 VOID
357 EXPORT
358 NdisGetSystemUpTime(OUT PULONG pSystemUpTime)
359 {
360 ULONG Increment;
361 LARGE_INTEGER TickCount;
362
363 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
364
365 /* Get the increment and current tick count */
366 Increment = KeQueryTimeIncrement();
367 KeQueryTickCount(&TickCount);
368
369 /* Convert to milliseconds and return */
370 TickCount.QuadPart *= Increment;
371 TickCount.QuadPart /= (10 * 1000);
372 *pSystemUpTime = TickCount.LowPart;
373 }
374
375 /*
376 * @implemented
377 */
378 #undef NdisInterlockedDecrement
379 LONG
380 EXPORT
381 NdisInterlockedDecrement(
382 IN PLONG Addend)
383 /*
384 * FUNCTION:
385 * ARGUMENTS:
386 * NOTES:
387 * NDIS 5.0
388 */
389 {
390 return InterlockedDecrement ( Addend );
391 }
392
393
394 /*
395 * @implemented
396 */
397 #undef NdisInterlockedIncrement
398 LONG
399 EXPORT
400 NdisInterlockedIncrement(
401 IN PLONG Addend)
402 /*
403 * FUNCTION:
404 * ARGUMENTS:
405 * NOTES:
406 * NDIS 5.0
407 */
408 {
409 return InterlockedIncrement ( Addend );
410 }
411
412
413 /*
414 * @implemented
415 */
416 #undef NdisInterlockedPopEntrySList
417 PSINGLE_LIST_ENTRY
418 EXPORT
419 NdisInterlockedPopEntrySList(
420 IN PSLIST_HEADER ListHead,
421 IN PKSPIN_LOCK Lock)
422 /*
423 * FUNCTION:
424 * ARGUMENTS:
425 * NOTES:
426 * NDIS 5.0
427 */
428 {
429 return (PSINGLE_LIST_ENTRY)ExInterlockedPopEntrySList ( ListHead, Lock );
430 }
431
432
433 /*
434 * @implemented
435 */
436 #undef NdisInterlockedPushEntrySList
437 PSINGLE_LIST_ENTRY
438 EXPORT
439 NdisInterlockedPushEntrySList(
440 IN PSLIST_HEADER ListHead,
441 IN PSINGLE_LIST_ENTRY ListEntry,
442 IN PKSPIN_LOCK Lock)
443 /*
444 * FUNCTION:
445 * ARGUMENTS:
446 * NOTES:
447 * NDIS 5.0
448 */
449 {
450 return (PSINGLE_LIST_ENTRY)ExInterlockedPushEntrySList ( ListHead, (PSLIST_ENTRY)ListEntry, Lock );
451 }
452
453
454 VOID
455 NTAPI
456 ndisProcWorkItemHandler(PVOID pContext)
457 {
458 PNDIS_WORK_ITEM pNdisItem = (PNDIS_WORK_ITEM)pContext;
459
460 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
461
462 pNdisItem->Routine(pNdisItem, pNdisItem->Context);
463 }
464
465 NDIS_STATUS
466 EXPORT
467 NdisScheduleWorkItem(
468 IN PNDIS_WORK_ITEM pWorkItem)
469 {
470 PWORK_QUEUE_ITEM pntWorkItem = (PWORK_QUEUE_ITEM)pWorkItem->WrapperReserved;
471
472 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
473
474 ExInitializeWorkItem(pntWorkItem, ndisProcWorkItemHandler, pWorkItem);
475 ExQueueWorkItem(pntWorkItem, DelayedWorkQueue);
476 return NDIS_STATUS_SUCCESS;
477 }
478
479 /*
480 * @implemented
481 */
482 VOID
483 EXPORT
484 NdisGetCurrentProcessorCpuUsage(
485 PULONG pCpuUsage)
486 /*
487 * FUNCTION: Returns how busy the current processor is as a percentage
488 * ARGUMENTS:
489 * pCpuUsage = Pointer to a buffer to place CPU usage
490 */
491 {
492 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
493
494 ExGetCurrentProcessorCpuUsage(pCpuUsage);
495 }
496
497 /*
498 * @implemented
499 */
500 ULONG
501 EXPORT
502 NdisGetSharedDataAlignment(VOID)
503 {
504 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
505
506 return KeGetRecommendedSharedDataAlignment();
507 }
508
509 /*
510 * @implemented
511 */
512 UINT
513 EXPORT
514 NdisGetVersion(VOID)
515 {
516 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
517
518 return NDIS_VERSION;
519 }
520
521 /*
522 * @implemented
523 */
524 UCHAR
525 EXPORT
526 NdisGeneratePartialCancelId(VOID)
527 {
528 UCHAR PartialCancelId;
529
530 PartialCancelId = (UCHAR)InterlockedIncrement(&CancelId);
531
532 NDIS_DbgPrint(MAX_TRACE, ("Cancel ID %u\n", PartialCancelId));
533
534 return PartialCancelId;
535 }
536
537 /* EOF */