2
* Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
16
#include "ntoskernel.h"
21
#include "ntoskernel_io_exports.h"
23
wstdcall void WIN_FUNC(IoAcquireCancelSpinLock,1)
24
(KIRQL *irql) __acquires(irql)
26
spin_lock_bh(&irp_cancel_lock);
30
wstdcall void WIN_FUNC(IoReleaseCancelSpinLock,1)
31
(KIRQL irql) __releases(irql)
33
spin_unlock_bh(&irp_cancel_lock);
36
wstdcall int WIN_FUNC(IoIsWdmVersionAvailable,2)
37
(UCHAR major, UCHAR minor)
39
IOENTER("%d, %x", major, minor);
41
(minor == 0x30 || // Windows 2003
42
minor == 0x20 || // Windows XP
43
minor == 0x10)) // Windows 2000
48
wstdcall BOOLEAN WIN_FUNC(IoIs32bitProcess,1)
58
wstdcall void WIN_FUNC(IoInitializeIrp,3)
59
(struct irp *irp, USHORT size, CCHAR stack_count)
61
IOENTER("irp: %p, %d, %d", irp, size, stack_count);
65
irp->stack_count = stack_count;
66
irp->current_location = stack_count;
67
IoGetCurrentIrpStackLocation(irp) = IRP_SL(irp, stack_count);
71
wstdcall void WIN_FUNC(IoReuseIrp,2)
72
(struct irp *irp, NTSTATUS status)
74
IOENTER("%p, %d", irp, status);
78
alloc_flags = irp->alloc_flags;
79
IoInitializeIrp(irp, irp->size, irp->stack_count);
80
irp->alloc_flags = alloc_flags;
81
irp->io_status.status = status;
86
wstdcall struct irp *WIN_FUNC(IoAllocateIrp,2)
87
(char stack_count, BOOLEAN charge_quota)
92
IOENTER("count: %d", stack_count);
94
irp_size = IoSizeOfIrp(stack_count);
95
irp = kmalloc(irp_size, irql_gfp());
97
IoInitializeIrp(irp, irp_size, stack_count);
98
IOTRACE("irp %p", irp);
102
wstdcall BOOLEAN WIN_FUNC(IoCancelIrp,1)
105
typeof(irp->cancel_routine) cancel_routine;
107
/* NB: this function may be called at DISPATCH_LEVEL */
108
IOTRACE("irp: %p", irp);
112
IoAcquireCancelSpinLock(&irp->cancel_irql);
113
cancel_routine = xchg(&irp->cancel_routine, NULL);
114
IOTRACE("%p", cancel_routine);
116
if (cancel_routine) {
117
struct io_stack_location *irp_sl;
118
irp_sl = IoGetCurrentIrpStackLocation(irp);
119
IOTRACE("%p, %p", irp_sl, irp_sl->dev_obj);
120
/* cancel_routine will release the spin lock */
121
__release(irp->cancel_irql);
122
LIN2WIN2(cancel_routine, irp_sl->dev_obj, irp);
123
/* in usb's cancel, irp->cancel is set to indicate
124
* status of cancel */
125
IOEXIT(return xchg(&irp->cancel, TRUE));
127
IOTRACE("irp %p already canceled", irp);
128
IoReleaseCancelSpinLock(irp->cancel_irql);
129
IOEXIT(return FALSE);
133
wstdcall void IoQueueThreadIrp(struct irp *irp)
135
struct nt_thread *thread;
138
thread = get_current_nt_thread();
140
IOTRACE("thread: %p, task: %p", thread, thread->task);
141
irp->flags |= IRP_SYNCHRONOUS_API;
142
irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);
143
InsertTailList(&thread->irps, &irp->thread_list);
144
IoIrpThread(irp) = thread;
145
nt_spin_unlock_irql(&thread->lock, irql);
147
IoIrpThread(irp) = NULL;
150
wstdcall void IoDequeueThreadIrp(struct irp *irp)
152
struct nt_thread *thread;
155
thread = IoIrpThread(irp);
157
irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);
158
RemoveEntryList(&irp->thread_list);
159
nt_spin_unlock_irql(&thread->lock, irql);
163
wstdcall void WIN_FUNC(IoFreeIrp,1)
166
IOENTER("irp = %p", irp);
167
if (irp->flags & IRP_SYNCHRONOUS_API)
168
IoDequeueThreadIrp(irp);
174
wstdcall struct irp *WIN_FUNC(IoBuildAsynchronousFsdRequest,6)
175
(ULONG major_fn, struct device_object *dev_obj, void *buffer,
176
ULONG length, LARGE_INTEGER *offset,
177
struct io_status_block *user_status)
180
struct io_stack_location *irp_sl;
182
IOENTER("%p", dev_obj);
185
irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
187
WARNING("couldn't allocate irp");
191
irp_sl = IoGetNextIrpStackLocation(irp);
192
irp_sl->major_fn = major_fn;
193
IOTRACE("major_fn: %d", major_fn);
194
irp_sl->minor_fn = 0;
197
irp_sl->dev_obj = dev_obj;
198
irp_sl->file_obj = NULL;
199
irp_sl->completion_routine = NULL;
201
if (dev_obj->flags & DO_DIRECT_IO) {
202
irp->mdl = IoAllocateMdl(buffer, length, FALSE, FALSE, irp);
203
if (irp->mdl == NULL) {
207
MmProbeAndLockPages(irp->mdl, KernelMode,
208
major_fn == IRP_MJ_WRITE ?
209
IoReadAccess : IoWriteAccess);
210
IOTRACE("mdl: %p", irp->mdl);
211
} else if (dev_obj->flags & DO_BUFFERED_IO) {
212
irp->associated_irp.system_buffer = buffer;
213
irp->flags = IRP_BUFFERED_IO;
215
IOTRACE("buffer: %p", buffer);
217
if (major_fn == IRP_MJ_READ) {
218
irp_sl->params.read.length = length;
219
irp_sl->params.read.byte_offset = *offset;
220
} else if (major_fn == IRP_MJ_WRITE) {
221
irp_sl->params.write.length = length;
222
irp_sl->params.write.byte_offset = *offset;
224
irp->user_status = user_status;
225
IOTRACE("irp: %p", irp);
229
wstdcall struct irp *WIN_FUNC(IoBuildSynchronousFsdRequest,7)
230
(ULONG major_fn, struct device_object *dev_obj, void *buf,
231
ULONG length, LARGE_INTEGER *offset, struct nt_event *event,
232
struct io_status_block *user_status)
236
irp = IoBuildAsynchronousFsdRequest(major_fn, dev_obj, buf, length,
237
offset, user_status);
240
irp->user_event = event;
241
IoQueueThreadIrp(irp);
245
wstdcall struct irp *WIN_FUNC(IoBuildDeviceIoControlRequest,9)
246
(ULONG ioctl, struct device_object *dev_obj,
247
void *input_buf, ULONG input_buf_len, void *output_buf,
248
ULONG output_buf_len, BOOLEAN internal_ioctl,
249
struct nt_event *event, struct io_status_block *io_status)
252
struct io_stack_location *irp_sl;
255
IOENTER("%p, 0x%08x, %d", dev_obj, ioctl, internal_ioctl);
258
irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
260
WARNING("couldn't allocate irp");
263
irp_sl = IoGetNextIrpStackLocation(irp);
264
irp_sl->params.dev_ioctl.code = ioctl;
265
irp_sl->params.dev_ioctl.input_buf_len = input_buf_len;
266
irp_sl->params.dev_ioctl.output_buf_len = output_buf_len;
267
irp_sl->major_fn = (internal_ioctl) ?
268
IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
269
IOTRACE("%d", IO_METHOD_FROM_CTL_CODE(ioctl));
271
switch (IO_METHOD_FROM_CTL_CODE(ioctl)) {
272
case METHOD_BUFFERED:
273
buf_len = max(input_buf_len, output_buf_len);
275
irp->associated_irp.system_buffer =
276
ExAllocatePoolWithTag(NonPagedPool, buf_len, 0);
277
if (!irp->associated_irp.system_buffer) {
281
irp->associated_irp.system_buffer = input_buf;
283
memcpy(irp->associated_irp.system_buffer,
284
input_buf, input_buf_len);
285
irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
287
irp->flags = IRP_INPUT_OPERATION;
288
irp->user_buf = output_buf;
290
irp->user_buf = NULL;
292
case METHOD_IN_DIRECT:
293
case METHOD_OUT_DIRECT:
295
irp->associated_irp.system_buffer =
296
ExAllocatePoolWithTag(NonPagedPool,
298
if (!irp->associated_irp.system_buffer) {
302
memcpy(irp->associated_irp.system_buffer,
303
input_buf, input_buf_len);
304
irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
306
/* TODO: we are supposed to setup MDL, but USB layer
307
* doesn't use MDLs. Moreover, USB layer mirrors
308
* non-DMAable buffers, so no need to allocate
309
* DMAable buffer here */
311
irp->associated_irp.system_buffer =
312
ExAllocatePoolWithTag(NonPagedPool,
314
if (!irp->associated_irp.system_buffer) {
318
irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
322
irp->user_buf = output_buf;
323
irp_sl->params.dev_ioctl.type3_input_buf = input_buf;
327
irp->user_status = io_status;
328
irp->user_event = event;
329
IoQueueThreadIrp(irp);
331
IOTRACE("irp: %p", irp);
335
wfastcall NTSTATUS WIN_FUNC(IofCallDriver,2)
336
(struct device_object *dev_obj, struct irp *irp)
338
struct io_stack_location *irp_sl;
340
driver_dispatch_t *major_func;
341
struct driver_object *drv_obj;
343
if (irp->current_location <= 0) {
344
ERROR("invalid irp: %p, %d", irp, irp->current_location);
345
return STATUS_INVALID_PARAMETER;
347
IOTRACE("%p, %p, %p, %d, %d, %p", dev_obj, irp, dev_obj->drv_obj,
348
irp->current_location, irp->stack_count,
349
IoGetCurrentIrpStackLocation(irp));
350
IoSetNextIrpStackLocation(irp);
352
irp_sl = IoGetCurrentIrpStackLocation(irp);
353
drv_obj = dev_obj->drv_obj;
354
irp_sl->dev_obj = dev_obj;
355
major_func = drv_obj->major_func[irp_sl->major_fn];
356
IOTRACE("major_func: %p, dev_obj: %p", major_func, dev_obj);
358
status = LIN2WIN2(major_func, dev_obj, irp);
360
ERROR("major_function %d is not implemented",
362
status = STATUS_NOT_SUPPORTED;
364
IOEXIT(return status);
367
wfastcall void WIN_FUNC(IofCompleteRequest,2)
368
(struct irp *irp, CHAR prio_boost)
370
struct io_stack_location *irp_sl;
374
if (irp->io_status.status == STATUS_PENDING) {
375
ERROR("invalid irp: %p, STATUS_PENDING", irp);
378
if (irp->current_location < 0 ||
379
irp->current_location >= irp->stack_count) {
380
ERROR("invalid irp: %p, %d", irp, irp->current_location);
384
for (irp_sl = IoGetCurrentIrpStackLocation(irp);
385
irp->current_location < irp->stack_count; irp_sl++) {
386
struct device_object *dev_obj;
390
if (irp_sl->control & SL_PENDING_RETURNED)
391
irp->pending_returned = TRUE;
393
/* current_location and dev_obj must be same as when
394
* driver called IoSetCompletionRoutine, which sets
395
* completion routine at next (lower) location, which
396
* is what we are going to call below; so we set
397
* current_location and dev_obj for the previous
398
* (higher) location */
399
IoSkipCurrentIrpStackLocation(irp);
400
if (irp->current_location < irp->stack_count)
401
dev_obj = IoGetCurrentIrpStackLocation(irp)->dev_obj;
405
IOTRACE("%d, %d, %p", irp->current_location, irp->stack_count,
407
if (irp_sl->completion_routine &&
408
((irp->io_status.status == STATUS_SUCCESS &&
409
irp_sl->control & SL_INVOKE_ON_SUCCESS) ||
410
(irp->io_status.status != STATUS_SUCCESS &&
411
irp_sl->control & SL_INVOKE_ON_ERROR) ||
412
(irp->cancel == TRUE &&
413
irp_sl->control & SL_INVOKE_ON_CANCEL))) {
414
IOTRACE("calling completion_routine at: %p, %p",
415
irp_sl->completion_routine, irp_sl->context);
416
status = LIN2WIN3(irp_sl->completion_routine,
417
dev_obj, irp, irp_sl->context);
418
IOTRACE("status: %08X", status);
419
if (status == STATUS_MORE_PROCESSING_REQUIRED)
422
/* propagate pending status to next irp_sl */
423
if (irp->pending_returned &&
424
irp->current_location < irp->stack_count)
425
IoMarkIrpPending(irp);
429
if (irp->user_status) {
430
irp->user_status->status = irp->io_status.status;
431
irp->user_status->info = irp->io_status.info;
434
if (irp->user_event) {
435
IOTRACE("setting event %p", irp->user_event);
436
KeSetEvent(irp->user_event, prio_boost, FALSE);
439
if (irp->associated_irp.system_buffer &&
440
(irp->flags & IRP_DEALLOCATE_BUFFER))
441
ExFreePool(irp->associated_irp.system_buffer);
444
while ((mdl = irp->mdl)) {
445
irp->mdl = mdl->next;
450
IOTRACE("freeing irp %p", irp);
455
wstdcall NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp)
457
IoSkipCurrentIrpStackLocation(irp);
458
IOEXIT(return IoCallDriver(dev_obj, irp));
461
wstdcall NTSTATUS IoIrpSyncComplete(struct device_object *dev_obj,
462
struct irp *irp, void *context)
464
if (irp->pending_returned == TRUE)
465
KeSetEvent(context, IO_NO_INCREMENT, FALSE);
466
IOEXIT(return STATUS_MORE_PROCESSING_REQUIRED);
468
WIN_FUNC_DECL(IoIrpSyncComplete,3)
470
wstdcall NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj,
473
struct nt_event event;
476
IoCopyCurrentIrpStackLocationToNext(irp);
477
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
478
/* completion function is called as Windows function */
479
IoSetCompletionRoutine(irp, WIN_FUNC_PTR(IoIrpSyncComplete,3), &event,
481
status = IoCallDriver(dev_obj, irp);
482
IOTRACE("%08X", status);
483
if (status == STATUS_PENDING) {
484
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE,
486
status = irp->io_status.status;
488
IOTRACE("%08X", status);
489
IOEXIT(return status);
491
WIN_FUNC_DECL(IoSyncForwardIrp,2)
493
wstdcall NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj,
498
IoCopyCurrentIrpStackLocationToNext(irp);
499
status = IoCallDriver(dev_obj, irp);
500
IOEXIT(return status);
502
WIN_FUNC_DECL(IoAsyncForwardIrp,2)
504
wstdcall NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj,
507
struct io_stack_location *irp_sl;
510
irp_sl = IoGetCurrentIrpStackLocation(irp);
511
WARNING("%d:%d not implemented", irp_sl->major_fn, irp_sl->minor_fn);
512
irp->io_status.status = STATUS_SUCCESS;
513
irp->io_status.info = 0;
514
status = irp->io_status.status;
515
IoCompleteRequest(irp, IO_NO_INCREMENT);
516
IOEXIT(return status);
518
WIN_FUNC_DECL(IoInvalidDeviceRequest,2)
520
static irqreturn_t io_irq_isr(int irq, void *data ISR_PT_REGS_PARAM_DECL)
522
struct kinterrupt *interrupt = data;
525
#ifdef CONFIG_DEBUG_SHIRQ
526
if (!interrupt->u.enabled)
527
EXIT1(return IRQ_NONE);
529
TRACE6("%p", interrupt);
530
nt_spin_lock(interrupt->actual_lock);
531
ret = LIN2WIN2(interrupt->isr, interrupt, interrupt->isr_ctx);
532
nt_spin_unlock(interrupt->actual_lock);
534
EXIT6(return IRQ_HANDLED);
536
EXIT6(return IRQ_NONE);
539
wstdcall NTSTATUS WIN_FUNC(IoConnectInterrupt,11)
540
(struct kinterrupt **kinterrupt, PKSERVICE_ROUTINE isr, void *isr_ctx,
541
NT_SPIN_LOCK *lock, ULONG vector, KIRQL irql, KIRQL synch_irql,
542
enum kinterrupt_mode mode, BOOLEAN shared, KAFFINITY cpu_mask,
545
struct kinterrupt *interrupt;
547
interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL);
549
IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
550
interrupt->vector = vector;
551
interrupt->cpu_mask = cpu_mask;
552
nt_spin_lock_init(&interrupt->lock);
554
interrupt->actual_lock = lock;
556
interrupt->actual_lock = &interrupt->lock;
557
interrupt->shared = shared;
558
interrupt->save_fp = save_fp;
559
interrupt->isr = isr;
560
interrupt->isr_ctx = isr_ctx;
561
InitializeListHead(&interrupt->list);
562
interrupt->irql = irql;
563
interrupt->synch_irql = synch_irql;
564
interrupt->mode = mode;
565
if (request_irq(vector, io_irq_isr, shared ? IRQF_SHARED : 0,
566
"ndiswrapper", interrupt)) {
567
WARNING("request for irq %d failed", vector);
569
IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
571
*kinterrupt = interrupt;
572
#ifdef CONFIG_DEBUG_SHIRQ
573
interrupt->u.enabled = 1;
575
IOEXIT(return STATUS_SUCCESS);
578
wstdcall void WIN_FUNC(IoDisconnectInterrupt,1)
579
(struct kinterrupt *interrupt)
581
#ifdef CONFIG_DEBUG_SHIRQ
582
interrupt->u.enabled = 0;
584
free_irq(interrupt->vector, interrupt);
588
wstdcall struct mdl *WIN_FUNC(IoAllocateMdl,5)
589
(void *virt, ULONG length, BOOLEAN second_buf, BOOLEAN charge_quota,
593
mdl = allocate_init_mdl(virt, length);
597
if (second_buf == TRUE) {
611
wstdcall void WIN_FUNC(IoFreeMdl,1)
618
wstdcall struct io_workitem *WIN_FUNC(IoAllocateWorkItem,1)
619
(struct device_object *dev_obj)
621
struct io_workitem *io_workitem;
623
IOENTER("%p", dev_obj);
624
io_workitem = kmalloc(sizeof(*io_workitem), irql_gfp());
627
io_workitem->dev_obj = dev_obj;
628
IOEXIT(return io_workitem);
631
wstdcall void WIN_FUNC(IoFreeWorkItem,1)
632
(struct io_workitem *io_workitem)
638
wstdcall void WIN_FUNC(IoQueueWorkItem,4)
639
(struct io_workitem *io_workitem, void *func,
640
enum work_queue_type queue_type, void *context)
642
IOENTER("%p, %p", io_workitem, io_workitem->dev_obj);
643
io_workitem->worker_routine = func;
644
io_workitem->context = context;
645
schedule_ntos_work_item(func, io_workitem->dev_obj, context);
649
wstdcall void WIN_FUNC(ExQueueWorkItem,2)
650
(struct io_workitem *io_workitem, enum work_queue_type queue_type)
652
IOENTER("%p", io_workitem);
653
schedule_ntos_work_item(io_workitem->worker_routine,
654
io_workitem->dev_obj, io_workitem->context);
657
wstdcall NTSTATUS WIN_FUNC(IoAllocateDriverObjectExtension,4)
658
(struct driver_object *drv_obj, void *client_id, ULONG extlen,
661
struct custom_ext *ce;
663
IOENTER("%p, %p", drv_obj, client_id);
664
ce = kmalloc(sizeof(*ce) + extlen, irql_gfp());
666
return STATUS_INSUFFICIENT_RESOURCES;
668
IOTRACE("custom_ext: %p", ce);
669
ce->client_id = client_id;
670
spin_lock_bh(&ntoskernel_lock);
671
InsertTailList(&drv_obj->drv_ext->custom_ext, &ce->list);
672
spin_unlock_bh(&ntoskernel_lock);
674
*ext = (void *)ce + sizeof(*ce);
675
IOTRACE("ext: %p", *ext);
676
IOEXIT(return STATUS_SUCCESS);
679
wstdcall void *WIN_FUNC(IoGetDriverObjectExtension,2)
680
(struct driver_object *drv_obj, void *client_id)
682
struct custom_ext *ce;
685
IOENTER("drv_obj: %p, client_id: %p", drv_obj, client_id);
687
spin_lock_bh(&ntoskernel_lock);
688
nt_list_for_each_entry(ce, &drv_obj->drv_ext->custom_ext, list) {
689
if (ce->client_id == client_id) {
690
ret = (void *)ce + sizeof(*ce);
694
spin_unlock_bh(&ntoskernel_lock);
695
IOTRACE("ret: %p", ret);
699
void free_custom_extensions(struct driver_extension *drv_ext)
703
IOENTER("%p", drv_ext);
704
spin_lock_bh(&ntoskernel_lock);
705
while ((ent = RemoveHeadList(&drv_ext->custom_ext)))
707
spin_unlock_bh(&ntoskernel_lock);
711
wstdcall NTSTATUS WIN_FUNC(IoCreateDevice,7)
712
(struct driver_object *drv_obj, ULONG dev_ext_length,
713
struct unicode_string *dev_name, DEVICE_TYPE dev_type,
714
ULONG dev_chars, BOOLEAN exclusive, struct device_object **newdev)
716
struct device_object *dev;
717
struct dev_obj_ext *dev_obj_ext;
720
IOENTER("%p, %u, %p", drv_obj, dev_ext_length, dev_name);
722
size = sizeof(*dev) + dev_ext_length + sizeof(*dev_obj_ext);
723
dev = allocate_object(size, OBJECT_TYPE_DEVICE, dev_name);
725
IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
727
dev->dev_ext = dev + 1;
731
dev_obj_ext = ((void *)(dev + 1)) + dev_ext_length;
732
dev_obj_ext->dev_obj = dev;
733
dev_obj_ext->size = 0;
734
dev_obj_ext->type = IO_TYPE_DEVICE;
735
dev->dev_obj_ext = dev_obj_ext;
737
dev->type = dev_type;
739
dev->size = sizeof(*dev) + dev_ext_length;
741
dev->attached = NULL;
742
dev->stack_count = 1;
744
dev->drv_obj = drv_obj;
745
dev->next = drv_obj->dev_obj;
746
drv_obj->dev_obj = dev;
749
dev->characteristics = dev_chars;
750
dev->io_timer = NULL;
751
KeInitializeEvent(&dev->lock, SynchronizationEvent, TRUE);
754
IOTRACE("dev: %p, ext: %p", dev, dev->dev_ext);
756
IOEXIT(return STATUS_SUCCESS);
759
wstdcall NTSTATUS WIN_FUNC(IoCreateUnprotectedSymbolicLink,2)
760
(struct unicode_string *link, struct unicode_string *dev_name)
762
struct ansi_string ansi;
764
IOENTER("%p, %p", dev_name, link);
765
if (dev_name && (RtlUnicodeStringToAnsiString(&ansi, dev_name, TRUE) ==
767
IOTRACE("dev_name: %s", ansi.buf);
768
RtlFreeAnsiString(&ansi);
770
if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) ==
772
IOTRACE("link: %s", ansi.buf);
773
RtlFreeAnsiString(&ansi);
776
IOEXIT(return STATUS_SUCCESS);
779
wstdcall NTSTATUS WIN_FUNC(IoCreateSymbolicLink,2)
780
(struct unicode_string *link, struct unicode_string *dev_name)
782
IOEXIT(return IoCreateUnprotectedSymbolicLink(link, dev_name));
785
wstdcall NTSTATUS WIN_FUNC(IoDeleteSymbolicLink,1)
786
(struct unicode_string *link)
788
struct ansi_string ansi;
791
if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) ==
793
IOTRACE("dev_name: %s", ansi.buf);
794
RtlFreeAnsiString(&ansi);
796
IOEXIT(return STATUS_SUCCESS);
799
wstdcall void WIN_FUNC(IoDeleteDevice,1)
800
(struct device_object *dev)
805
IOTRACE("drv_obj: %p", dev->drv_obj);
807
struct device_object *prev;
809
prev = dev->drv_obj->dev_obj;
810
IOTRACE("dev_obj: %p", prev);
812
dev->drv_obj->dev_obj = dev->next;
814
while (prev->next != dev)
816
prev->next = dev->next;
819
ObDereferenceObject(dev);
823
wstdcall void WIN_FUNC(IoDetachDevice,1)
824
(struct device_object *tgt)
826
struct device_object *tail;
831
tail = tgt->attached;
834
IOTRACE("tail: %p", tail);
836
spin_lock_bh(&ntoskernel_lock);
837
tgt->attached = tail->attached;
838
IOTRACE("attached:%p", tgt->attached);
839
for ( ; tail; tail = tail->attached) {
840
IOTRACE("tail:%p", tail);
843
spin_unlock_bh(&ntoskernel_lock);
847
wstdcall struct device_object *WIN_FUNC(IoGetAttachedDevice,1)
848
(struct device_object *dev)
853
spin_lock_bh(&ntoskernel_lock);
854
while (dev->attached)
856
spin_unlock_bh(&ntoskernel_lock);
860
wstdcall struct device_object *WIN_FUNC(IoGetAttachedDeviceReference,1)
861
(struct device_object *dev)
866
dev = IoGetAttachedDevice(dev);
867
ObReferenceObject(dev);
871
wstdcall struct device_object *WIN_FUNC(IoAttachDeviceToDeviceStack,2)
872
(struct device_object *src, struct device_object *tgt)
874
struct device_object *attached;
875
struct dev_obj_ext *src_dev_ext;
877
IOENTER("%p, %p", src, tgt);
878
attached = IoGetAttachedDevice(tgt);
879
IOTRACE("%p", attached);
880
src_dev_ext = src->dev_obj_ext;
881
spin_lock_bh(&ntoskernel_lock);
883
attached->attached = src;
884
src->attached = NULL;
885
src->stack_count = attached->stack_count + 1;
886
src_dev_ext->attached_to = attached;
887
spin_unlock_bh(&ntoskernel_lock);
888
IOTRACE("stack_count: %d -> %d", attached->stack_count,
890
IOEXIT(return attached);
893
wstdcall NTSTATUS WIN_FUNC(IoGetDeviceProperty,5)
894
(struct device_object *pdo, enum device_registry_property dev_property,
895
ULONG buffer_len, void *buffer, ULONG *result_len)
897
struct ansi_string ansi;
898
struct unicode_string unicode;
899
struct wrap_device *wd;
902
IOENTER("dev_obj = %p, dev_property = %d, buffer_len = %u, "
903
"buffer = %p, result_len = %p", pdo, dev_property,
904
buffer_len, buffer, result_len);
907
switch (dev_property) {
908
case DevicePropertyDeviceDescription:
909
case DevicePropertyFriendlyName:
910
case DevicePropertyDriverKeyName:
911
if (wrap_is_pci_bus(wd->dev_bus))
912
RtlInitAnsiString(&ansi, "PCI");
913
else // if (wrap_is_usb_bus(wd->dev_bus))
914
RtlInitAnsiString(&ansi, "USB");
915
need = sizeof(wchar_t) * (ansi.max_length + 1);
916
if (buffer_len < need) {
918
IOEXIT(return STATUS_BUFFER_TOO_SMALL);
920
unicode.max_length = buffer_len;
921
unicode.buf = buffer;
922
if (RtlAnsiStringToUnicodeString(&unicode, &ansi,
923
FALSE) != STATUS_SUCCESS) {
924
*result_len = unicode.length;
925
IOEXIT(return STATUS_BUFFER_TOO_SMALL);
927
IOEXIT(return STATUS_SUCCESS);
929
WARNING("%d not implemented", dev_property);
930
IOEXIT(return STATUS_INVALID_PARAMETER_2);
934
wstdcall NTSTATUS WIN_FUNC(IoGetDeviceObjectPointer,4)
935
(struct unicode_string *name, ACCESS_MASK desired_access,
936
void *file_obj, struct device_object *dev_obj)
938
struct common_object_header *coh;
941
/* TODO: access is not checked and file_obj is set to NULL */
943
spin_lock_bh(&ntoskernel_lock);
944
nt_list_for_each_entry(coh, &object_list, list) {
945
TRACE5("header: %p, type: %d", coh, coh->type);
946
if (coh->type != OBJECT_TYPE_DEVICE)
948
if (!RtlCompareUnicodeString(&coh->name, name, TRUE)) {
949
dev_obj = HEADER_TO_OBJECT(coh);
950
TRACE5("dev_obj: %p", dev_obj);
954
spin_unlock_bh(&ntoskernel_lock);
956
IOEXIT(return STATUS_SUCCESS);
958
IOEXIT(return STATUS_OBJECT_NAME_INVALID);
961
/* NOTE: Make sure to compile with -freg-struct-return, so gcc will
962
* return union in register, like Windows */
963
wstdcall union power_state WIN_FUNC(PoSetPowerState,3)
964
(struct device_object *dev_obj, enum power_state_type type,
965
union power_state state)
967
IOEXIT(return state);
970
wstdcall NTSTATUS WIN_FUNC(PoCallDriver,2)
971
(struct device_object *dev_obj, struct irp *irp)
973
return IoCallDriver(dev_obj, irp);
976
wstdcall NTSTATUS WIN_FUNC(PoRequestPowerIrp,6)
977
(struct device_object *dev_obj, UCHAR minor_fn,
978
union power_state power_state, void *completion_func,
979
void *context, struct irp **pirp)
982
struct io_stack_location *irp_sl;
984
TRACE1("%p, %d, %p", dev_obj, dev_obj->stack_count, dev_obj->drv_obj);
985
irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
987
return STATUS_INSUFFICIENT_RESOURCES;
988
irp_sl = IoGetNextIrpStackLocation(irp);
989
irp_sl->major_fn = IRP_MJ_POWER;
990
irp_sl->minor_fn = minor_fn;
991
if (minor_fn == IRP_MN_WAIT_WAKE)
992
irp_sl->params.power.type = SystemPowerState;
994
irp_sl->params.power.type = DevicePowerState;
995
irp_sl->params.power.state = power_state;
996
irp_sl->completion_routine = completion_func;
997
irp->io_status.status = STATUS_NOT_SUPPORTED;
999
return PoCallDriver(dev_obj, irp);
1002
wstdcall void WIN_FUNC(PoStartNextPowerIrp,1)
1005
IOENTER("irp = %p", irp);
1009
wstdcall void WIN_FUNC(IoInitializeRemoveLockEx,5)
1010
(struct io_remove_lock *lock, ULONG alloc_tag, ULONG max_locked_min,
1011
ULONG high_mark, ULONG lock_size)
1016
wstdcall void *WIN_FUNC(IoAllocateErrorLogEntry,2)
1017
(void *io_object, UCHAR entry_size)
1019
/* not implemented fully */
1020
void *ret = kmalloc(sizeof(struct io_error_log_packet) + entry_size,
1024
return ret + sizeof(struct io_error_log_packet);
1029
wstdcall void WIN_FUNC(IoWriteErrorLogEntry,1)
1032
/* TODO: log error with codes and message */
1036
wstdcall void WIN_FUNC(IoFreeErrorLogEntry,1)
1039
TRACE2("%p", entry);
1040
kfree(entry - sizeof(struct io_error_log_packet));
1043
wstdcall NTSTATUS WIN_FUNC(IoAcquireRemoveLockEx,5)
1044
(struct io_remove_lock lock, void *tag, char *file, ULONG line,
1048
IOEXIT(return STATUS_SUCCESS);
1051
wstdcall NTSTATUS WIN_FUNC(IoReleaseRemoveLockEx,3)
1052
(struct io_remove_lock lock, void *tag, ULONG lock_size)
1055
IOEXIT(return STATUS_SUCCESS);
1058
wstdcall NTSTATUS WIN_FUNC(IoRegisterDeviceInterface,4)
1059
(struct device_object *pdo, struct guid *guid_class,
1060
struct unicode_string *reference, struct unicode_string *link)
1062
struct ansi_string ansi;
1064
/* TODO: check if pdo is valid */
1065
RtlInitAnsiString(&ansi, "ndis");
1066
ENTER1("pdo: %p, ref: %p, link: %p, %x, %x, %x", pdo, reference, link,
1067
guid_class->data1, guid_class->data2, guid_class->data3);
1068
return RtlAnsiStringToUnicodeString(link, &ansi, TRUE);
1071
wstdcall NTSTATUS WIN_FUNC(IoSetDeviceInterfaceState,2)
1072
(struct unicode_string *link, BOOLEAN enable)
1074
ENTER1("link: %p, enable: %d", link, enable);
1075
return STATUS_SUCCESS;
1078
wstdcall NTSTATUS WIN_FUNC(IoOpenDeviceRegistryKey,4)
1079
(struct device_object *dev_obj, ULONG type, ACCESS_MASK mask,
1082
ENTER1("dev_obj: %p", dev_obj);
1084
return STATUS_SUCCESS;
1087
wstdcall NTSTATUS WIN_FUNC(IoWMIRegistrationControl,2)
1088
(struct device_object *dev_obj, ULONG action)
1090
ENTER2("%p, %d", dev_obj, action);
1091
EXIT2(return STATUS_SUCCESS);
1094
wstdcall void WIN_FUNC(IoInvalidateDeviceRelations,2)
1095
(struct device_object *dev_obj, enum device_relation_type type)
1097
INFO("%p, %d", dev_obj, type);
1101
wstdcall void WIN_FUNC(IoInvalidateDeviceState,1)
1102
(struct device_object *pdo)