~ubuntu-branches/ubuntu/quantal/linux-lowlatency/quantal

« back to all changes in this revision

Viewing changes to ubuntu/ndiswrapper/ntoskernel_io.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-04kado7d1u2er2rl
Tags: 3.2.0-16.25
Add new lowlatency kernel flavour

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
14
 */
 
15
 
 
16
#include "ntoskernel.h"
 
17
#include "ndis.h"
 
18
#include "wrapndis.h"
 
19
#include "usb.h"
 
20
#include "loader.h"
 
21
#include "ntoskernel_io_exports.h"
 
22
 
 
23
wstdcall void WIN_FUNC(IoAcquireCancelSpinLock,1)
 
24
        (KIRQL *irql) __acquires(irql)
 
25
{
 
26
        spin_lock_bh(&irp_cancel_lock);
 
27
        *irql = 0;
 
28
}
 
29
 
 
30
wstdcall void WIN_FUNC(IoReleaseCancelSpinLock,1)
 
31
        (KIRQL irql) __releases(irql)
 
32
{
 
33
        spin_unlock_bh(&irp_cancel_lock);
 
34
}
 
35
 
 
36
wstdcall int WIN_FUNC(IoIsWdmVersionAvailable,2)
 
37
        (UCHAR major, UCHAR minor)
 
38
{
 
39
        IOENTER("%d, %x", major, minor);
 
40
        if (major == 1 &&
 
41
            (minor == 0x30 || // Windows 2003
 
42
             minor == 0x20 || // Windows XP
 
43
             minor == 0x10)) // Windows 2000
 
44
                IOEXIT(return TRUE);
 
45
        IOEXIT(return FALSE);
 
46
}
 
47
 
 
48
wstdcall BOOLEAN WIN_FUNC(IoIs32bitProcess,1)
 
49
        (struct irp *irp)
 
50
{
 
51
#ifdef CONFIG_X86_64
 
52
        return FALSE;
 
53
#else
 
54
        return TRUE;
 
55
#endif
 
56
}
 
57
 
 
58
wstdcall void WIN_FUNC(IoInitializeIrp,3)
 
59
        (struct irp *irp, USHORT size, CCHAR stack_count)
 
60
{
 
61
        IOENTER("irp: %p, %d, %d", irp, size, stack_count);
 
62
 
 
63
        memset(irp, 0, size);
 
64
        irp->size = size;
 
65
        irp->stack_count = stack_count;
 
66
        irp->current_location = stack_count;
 
67
        IoGetCurrentIrpStackLocation(irp) = IRP_SL(irp, stack_count);
 
68
        IOEXIT(return);
 
69
}
 
70
 
 
71
wstdcall void WIN_FUNC(IoReuseIrp,2)
 
72
        (struct irp *irp, NTSTATUS status)
 
73
{
 
74
        IOENTER("%p, %d", irp, status);
 
75
        if (irp) {
 
76
                UCHAR alloc_flags;
 
77
 
 
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;
 
82
        }
 
83
        IOEXIT(return);
 
84
}
 
85
 
 
86
wstdcall struct irp *WIN_FUNC(IoAllocateIrp,2)
 
87
        (char stack_count, BOOLEAN charge_quota)
 
88
{
 
89
        struct irp *irp;
 
90
        int irp_size;
 
91
 
 
92
        IOENTER("count: %d", stack_count);
 
93
        stack_count++;
 
94
        irp_size = IoSizeOfIrp(stack_count);
 
95
        irp = kmalloc(irp_size, irql_gfp());
 
96
        if (irp)
 
97
                IoInitializeIrp(irp, irp_size, stack_count);
 
98
        IOTRACE("irp %p", irp);
 
99
        IOEXIT(return irp);
 
100
}
 
101
 
 
102
wstdcall BOOLEAN WIN_FUNC(IoCancelIrp,1)
 
103
        (struct irp *irp)
 
104
{
 
105
        typeof(irp->cancel_routine) cancel_routine;
 
106
 
 
107
        /* NB: this function may be called at DISPATCH_LEVEL */
 
108
        IOTRACE("irp: %p", irp);
 
109
        if (!irp)
 
110
                return FALSE;
 
111
        DUMP_IRP(irp);
 
112
        IoAcquireCancelSpinLock(&irp->cancel_irql);
 
113
        cancel_routine = xchg(&irp->cancel_routine, NULL);
 
114
        IOTRACE("%p", cancel_routine);
 
115
        irp->cancel = TRUE;
 
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));
 
126
        } else {
 
127
                IOTRACE("irp %p already canceled", irp);
 
128
                IoReleaseCancelSpinLock(irp->cancel_irql);
 
129
                IOEXIT(return FALSE);
 
130
        }
 
131
}
 
132
 
 
133
wstdcall void IoQueueThreadIrp(struct irp *irp)
 
134
{
 
135
        struct nt_thread *thread;
 
136
        KIRQL irql;
 
137
 
 
138
        thread = get_current_nt_thread();
 
139
        if (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);
 
146
        } else
 
147
                IoIrpThread(irp) = NULL;
 
148
}
 
149
 
 
150
wstdcall void IoDequeueThreadIrp(struct irp *irp)
 
151
{
 
152
        struct nt_thread *thread;
 
153
        KIRQL irql;
 
154
 
 
155
        thread = IoIrpThread(irp);
 
156
        if (thread) {
 
157
                irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);
 
158
                RemoveEntryList(&irp->thread_list);
 
159
                nt_spin_unlock_irql(&thread->lock, irql);
 
160
        }
 
161
}
 
162
 
 
163
wstdcall void WIN_FUNC(IoFreeIrp,1)
 
164
        (struct irp *irp)
 
165
{
 
166
        IOENTER("irp = %p", irp);
 
167
        if (irp->flags & IRP_SYNCHRONOUS_API)
 
168
                IoDequeueThreadIrp(irp);
 
169
        kfree(irp);
 
170
 
 
171
        IOEXIT(return);
 
172
}
 
173
 
 
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)
 
178
{
 
179
        struct irp *irp;
 
180
        struct io_stack_location *irp_sl;
 
181
 
 
182
        IOENTER("%p", dev_obj);
 
183
        if (!dev_obj)
 
184
                IOEXIT(return NULL);
 
185
        irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
 
186
        if (irp == NULL) {
 
187
                WARNING("couldn't allocate irp");
 
188
                IOEXIT(return NULL);
 
189
        }
 
190
 
 
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;
 
195
        irp_sl->flags = 0;
 
196
        irp_sl->control = 0;
 
197
        irp_sl->dev_obj = dev_obj;
 
198
        irp_sl->file_obj = NULL;
 
199
        irp_sl->completion_routine = NULL;
 
200
 
 
201
        if (dev_obj->flags & DO_DIRECT_IO) {
 
202
                irp->mdl = IoAllocateMdl(buffer, length, FALSE, FALSE, irp);
 
203
                if (irp->mdl == NULL) {
 
204
                        IoFreeIrp(irp);
 
205
                        return NULL;
 
206
                }
 
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;
 
214
                irp->mdl = NULL;
 
215
                IOTRACE("buffer: %p", buffer);
 
216
        }
 
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;
 
223
        }
 
224
        irp->user_status = user_status;
 
225
        IOTRACE("irp: %p", irp);
 
226
        return irp;
 
227
}
 
228
 
 
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)
 
233
{
 
234
        struct irp *irp;
 
235
 
 
236
        irp = IoBuildAsynchronousFsdRequest(major_fn, dev_obj, buf, length,
 
237
                                            offset, user_status);
 
238
        if (irp == NULL)
 
239
                return NULL;
 
240
        irp->user_event = event;
 
241
        IoQueueThreadIrp(irp);
 
242
        return irp;
 
243
}
 
244
 
 
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)
 
250
{
 
251
        struct irp *irp;
 
252
        struct io_stack_location *irp_sl;
 
253
        ULONG buf_len;
 
254
 
 
255
        IOENTER("%p, 0x%08x, %d", dev_obj, ioctl, internal_ioctl);
 
256
        if (!dev_obj)
 
257
                IOEXIT(return NULL);
 
258
        irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
 
259
        if (irp == NULL) {
 
260
                WARNING("couldn't allocate irp");
 
261
                return NULL;
 
262
        }
 
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));
 
270
 
 
271
        switch (IO_METHOD_FROM_CTL_CODE(ioctl)) {
 
272
        case METHOD_BUFFERED:
 
273
                buf_len = max(input_buf_len, output_buf_len);
 
274
                if (buf_len) {
 
275
                        irp->associated_irp.system_buffer =
 
276
                                ExAllocatePoolWithTag(NonPagedPool, buf_len, 0);
 
277
                        if (!irp->associated_irp.system_buffer) {
 
278
                                IoFreeIrp(irp);
 
279
                                IOEXIT(return NULL);
 
280
                        }
 
281
                        irp->associated_irp.system_buffer = input_buf;
 
282
                        if (input_buf)
 
283
                                memcpy(irp->associated_irp.system_buffer,
 
284
                                       input_buf, input_buf_len);
 
285
                        irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
 
286
                        if (output_buf)
 
287
                                irp->flags = IRP_INPUT_OPERATION;
 
288
                        irp->user_buf = output_buf;
 
289
                } else
 
290
                        irp->user_buf = NULL;
 
291
                break;
 
292
        case METHOD_IN_DIRECT:
 
293
        case METHOD_OUT_DIRECT:
 
294
                if (input_buf) {
 
295
                        irp->associated_irp.system_buffer =
 
296
                                ExAllocatePoolWithTag(NonPagedPool,
 
297
                                                      input_buf_len, 0);
 
298
                        if (!irp->associated_irp.system_buffer) {
 
299
                                IoFreeIrp(irp);
 
300
                                IOEXIT(return NULL);
 
301
                        }
 
302
                        memcpy(irp->associated_irp.system_buffer,
 
303
                               input_buf, input_buf_len);
 
304
                        irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
 
305
                }
 
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 */
 
310
                if (output_buf) {
 
311
                        irp->associated_irp.system_buffer =
 
312
                                ExAllocatePoolWithTag(NonPagedPool,
 
313
                                                      output_buf_len, 0);
 
314
                        if (!irp->associated_irp.system_buffer) {
 
315
                                IoFreeIrp(irp);
 
316
                                IOEXIT(return NULL);
 
317
                        }
 
318
                        irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
 
319
                }
 
320
                break;
 
321
        case METHOD_NEITHER:
 
322
                irp->user_buf = output_buf;
 
323
                irp_sl->params.dev_ioctl.type3_input_buf = input_buf;
 
324
                break;
 
325
        }
 
326
 
 
327
        irp->user_status = io_status;
 
328
        irp->user_event = event;
 
329
        IoQueueThreadIrp(irp);
 
330
 
 
331
        IOTRACE("irp: %p", irp);
 
332
        IOEXIT(return irp);
 
333
}
 
334
 
 
335
wfastcall NTSTATUS WIN_FUNC(IofCallDriver,2)
 
336
        (struct device_object *dev_obj, struct irp *irp)
 
337
{
 
338
        struct io_stack_location *irp_sl;
 
339
        NTSTATUS status;
 
340
        driver_dispatch_t *major_func;
 
341
        struct driver_object *drv_obj;
 
342
 
 
343
        if (irp->current_location <= 0) {
 
344
                ERROR("invalid irp: %p, %d", irp, irp->current_location);
 
345
                return STATUS_INVALID_PARAMETER;
 
346
        }
 
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);
 
351
        DUMP_IRP(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);
 
357
        if (major_func)
 
358
                status = LIN2WIN2(major_func, dev_obj, irp);
 
359
        else {
 
360
                ERROR("major_function %d is not implemented",
 
361
                      irp_sl->major_fn);
 
362
                status = STATUS_NOT_SUPPORTED;
 
363
        }
 
364
        IOEXIT(return status);
 
365
}
 
366
 
 
367
wfastcall void WIN_FUNC(IofCompleteRequest,2)
 
368
        (struct irp *irp, CHAR prio_boost)
 
369
{
 
370
        struct io_stack_location *irp_sl;
 
371
 
 
372
#ifdef IO_DEBUG
 
373
        DUMP_IRP(irp);
 
374
        if (irp->io_status.status == STATUS_PENDING) {
 
375
                ERROR("invalid irp: %p, STATUS_PENDING", irp);
 
376
                return;
 
377
        }
 
378
        if (irp->current_location < 0 ||
 
379
            irp->current_location >= irp->stack_count) {
 
380
                ERROR("invalid irp: %p, %d", irp, irp->current_location);
 
381
                return;
 
382
        }
 
383
#endif
 
384
        for (irp_sl = IoGetCurrentIrpStackLocation(irp);
 
385
             irp->current_location < irp->stack_count; irp_sl++) {
 
386
                struct device_object *dev_obj;
 
387
                NTSTATUS status;
 
388
 
 
389
                DUMP_IRP(irp);
 
390
                if (irp_sl->control & SL_PENDING_RETURNED)
 
391
                        irp->pending_returned = TRUE;
 
392
 
 
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;
 
402
                else
 
403
                        dev_obj = NULL;
 
404
 
 
405
                IOTRACE("%d, %d, %p", irp->current_location, irp->stack_count,
 
406
                        dev_obj);
 
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)
 
420
                                IOEXIT(return);
 
421
                } else {
 
422
                        /* propagate pending status to next irp_sl */
 
423
                        if (irp->pending_returned &&
 
424
                            irp->current_location < irp->stack_count)
 
425
                                IoMarkIrpPending(irp);
 
426
                }
 
427
        }
 
428
 
 
429
        if (irp->user_status) {
 
430
                irp->user_status->status = irp->io_status.status;
 
431
                irp->user_status->info = irp->io_status.info;
 
432
        }
 
433
 
 
434
        if (irp->user_event) {
 
435
                IOTRACE("setting event %p", irp->user_event);
 
436
                KeSetEvent(irp->user_event, prio_boost, FALSE);
 
437
        }
 
438
 
 
439
        if (irp->associated_irp.system_buffer &&
 
440
            (irp->flags & IRP_DEALLOCATE_BUFFER))
 
441
                ExFreePool(irp->associated_irp.system_buffer);
 
442
        else {
 
443
                struct mdl *mdl;
 
444
                while ((mdl = irp->mdl)) {
 
445
                        irp->mdl = mdl->next;
 
446
                        MmUnlockPages(mdl);
 
447
                        IoFreeMdl(mdl);
 
448
                }
 
449
        }
 
450
        IOTRACE("freeing irp %p", irp);
 
451
        IoFreeIrp(irp);
 
452
        IOEXIT(return);
 
453
}
 
454
 
 
455
wstdcall NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp)
 
456
{
 
457
        IoSkipCurrentIrpStackLocation(irp);
 
458
        IOEXIT(return IoCallDriver(dev_obj, irp));
 
459
}
 
460
 
 
461
wstdcall NTSTATUS IoIrpSyncComplete(struct device_object *dev_obj,
 
462
                                    struct irp *irp, void *context)
 
463
{
 
464
        if (irp->pending_returned == TRUE)
 
465
                KeSetEvent(context, IO_NO_INCREMENT, FALSE);
 
466
        IOEXIT(return STATUS_MORE_PROCESSING_REQUIRED);
 
467
}
 
468
WIN_FUNC_DECL(IoIrpSyncComplete,3)
 
469
 
 
470
wstdcall NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj,
 
471
                                   struct irp *irp)
 
472
{
 
473
        struct nt_event event;
 
474
        NTSTATUS status;
 
475
 
 
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,
 
480
                               TRUE, TRUE, TRUE);
 
481
        status = IoCallDriver(dev_obj, irp);
 
482
        IOTRACE("%08X", status);
 
483
        if (status == STATUS_PENDING) {
 
484
                KeWaitForSingleObject(&event, Executive, KernelMode, FALSE,
 
485
                                      NULL);
 
486
                status = irp->io_status.status;
 
487
        }
 
488
        IOTRACE("%08X", status);
 
489
        IOEXIT(return status);
 
490
}
 
491
WIN_FUNC_DECL(IoSyncForwardIrp,2)
 
492
 
 
493
wstdcall NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj,
 
494
                                    struct irp *irp)
 
495
{
 
496
        NTSTATUS status;
 
497
 
 
498
        IoCopyCurrentIrpStackLocationToNext(irp);
 
499
        status = IoCallDriver(dev_obj, irp);
 
500
        IOEXIT(return status);
 
501
}
 
502
WIN_FUNC_DECL(IoAsyncForwardIrp,2)
 
503
 
 
504
wstdcall NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj,
 
505
                                         struct irp *irp)
 
506
{
 
507
        struct io_stack_location *irp_sl;
 
508
        NTSTATUS status;
 
509
 
 
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);
 
517
}
 
518
WIN_FUNC_DECL(IoInvalidDeviceRequest,2)
 
519
 
 
520
static irqreturn_t io_irq_isr(int irq, void *data ISR_PT_REGS_PARAM_DECL)
 
521
{
 
522
        struct kinterrupt *interrupt = data;
 
523
        BOOLEAN ret;
 
524
 
 
525
#ifdef CONFIG_DEBUG_SHIRQ
 
526
        if (!interrupt->u.enabled)
 
527
                EXIT1(return IRQ_NONE);
 
528
#endif
 
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);
 
533
        if (ret == TRUE)
 
534
                EXIT6(return IRQ_HANDLED);
 
535
        else
 
536
                EXIT6(return IRQ_NONE);
 
537
}
 
538
 
 
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,
 
543
         BOOLEAN save_fp)
 
544
{
 
545
        struct kinterrupt *interrupt;
 
546
        IOENTER("");
 
547
        interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL);
 
548
        if (!interrupt)
 
549
                IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
 
550
        interrupt->vector = vector;
 
551
        interrupt->cpu_mask = cpu_mask;
 
552
        nt_spin_lock_init(&interrupt->lock);
 
553
        if (lock)
 
554
                interrupt->actual_lock = lock;
 
555
        else
 
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);
 
568
                kfree(interrupt);
 
569
                IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
 
570
        }
 
571
        *kinterrupt = interrupt;
 
572
#ifdef CONFIG_DEBUG_SHIRQ
 
573
        interrupt->u.enabled = 1;
 
574
#endif
 
575
        IOEXIT(return STATUS_SUCCESS);
 
576
}
 
577
 
 
578
wstdcall void WIN_FUNC(IoDisconnectInterrupt,1)
 
579
        (struct kinterrupt *interrupt)
 
580
{
 
581
#ifdef CONFIG_DEBUG_SHIRQ
 
582
        interrupt->u.enabled = 0;
 
583
#endif
 
584
        free_irq(interrupt->vector, interrupt);
 
585
        kfree(interrupt);
 
586
}
 
587
 
 
588
wstdcall struct mdl *WIN_FUNC(IoAllocateMdl,5)
 
589
        (void *virt, ULONG length, BOOLEAN second_buf, BOOLEAN charge_quota,
 
590
         struct irp *irp)
 
591
{
 
592
        struct mdl *mdl;
 
593
        mdl = allocate_init_mdl(virt, length);
 
594
        if (!mdl)
 
595
                return NULL;
 
596
        if (irp) {
 
597
                if (second_buf == TRUE) {
 
598
                        struct mdl *last;
 
599
 
 
600
                        last = irp->mdl;
 
601
                        while (last->next)
 
602
                                last = last->next;
 
603
                        last->next = mdl;
 
604
                } else
 
605
                        irp->mdl = mdl;
 
606
        }
 
607
        IOTRACE("%p", mdl);
 
608
        return mdl;
 
609
}
 
610
 
 
611
wstdcall void WIN_FUNC(IoFreeMdl,1)
 
612
        (struct mdl *mdl)
 
613
{
 
614
        IOTRACE("%p", mdl);
 
615
        free_mdl(mdl);
 
616
}
 
617
 
 
618
wstdcall struct io_workitem *WIN_FUNC(IoAllocateWorkItem,1)
 
619
        (struct device_object *dev_obj)
 
620
{
 
621
        struct io_workitem *io_workitem;
 
622
 
 
623
        IOENTER("%p", dev_obj);
 
624
        io_workitem = kmalloc(sizeof(*io_workitem), irql_gfp());
 
625
        if (!io_workitem)
 
626
                IOEXIT(return NULL);
 
627
        io_workitem->dev_obj = dev_obj;
 
628
        IOEXIT(return io_workitem);
 
629
}
 
630
 
 
631
wstdcall void WIN_FUNC(IoFreeWorkItem,1)
 
632
        (struct io_workitem *io_workitem)
 
633
{
 
634
        kfree(io_workitem);
 
635
        IOEXIT(return);
 
636
}
 
637
 
 
638
wstdcall void WIN_FUNC(IoQueueWorkItem,4)
 
639
        (struct io_workitem *io_workitem, void *func,
 
640
         enum work_queue_type queue_type, void *context)
 
641
{
 
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);
 
646
        IOEXIT(return);
 
647
}
 
648
 
 
649
wstdcall void WIN_FUNC(ExQueueWorkItem,2)
 
650
        (struct io_workitem *io_workitem, enum work_queue_type queue_type)
 
651
{
 
652
        IOENTER("%p", io_workitem);
 
653
        schedule_ntos_work_item(io_workitem->worker_routine,
 
654
                                io_workitem->dev_obj, io_workitem->context);
 
655
}
 
656
 
 
657
wstdcall NTSTATUS WIN_FUNC(IoAllocateDriverObjectExtension,4)
 
658
        (struct driver_object *drv_obj, void *client_id, ULONG extlen,
 
659
         void **ext)
 
660
{
 
661
        struct custom_ext *ce;
 
662
 
 
663
        IOENTER("%p, %p", drv_obj, client_id);
 
664
        ce = kmalloc(sizeof(*ce) + extlen, irql_gfp());
 
665
        if (ce == NULL)
 
666
                return STATUS_INSUFFICIENT_RESOURCES;
 
667
 
 
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);
 
673
 
 
674
        *ext = (void *)ce + sizeof(*ce);
 
675
        IOTRACE("ext: %p", *ext);
 
676
        IOEXIT(return STATUS_SUCCESS);
 
677
}
 
678
 
 
679
wstdcall void *WIN_FUNC(IoGetDriverObjectExtension,2)
 
680
        (struct driver_object *drv_obj, void *client_id)
 
681
{
 
682
        struct custom_ext *ce;
 
683
        void *ret;
 
684
 
 
685
        IOENTER("drv_obj: %p, client_id: %p", drv_obj, client_id);
 
686
        ret = NULL;
 
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);
 
691
                        break;
 
692
                }
 
693
        }
 
694
        spin_unlock_bh(&ntoskernel_lock);
 
695
        IOTRACE("ret: %p", ret);
 
696
        return ret;
 
697
}
 
698
 
 
699
void free_custom_extensions(struct driver_extension *drv_ext)
 
700
{
 
701
        struct nt_list *ent;
 
702
 
 
703
        IOENTER("%p", drv_ext);
 
704
        spin_lock_bh(&ntoskernel_lock);
 
705
        while ((ent = RemoveHeadList(&drv_ext->custom_ext)))
 
706
                kfree(ent);
 
707
        spin_unlock_bh(&ntoskernel_lock);
 
708
        IOEXIT(return);
 
709
}
 
710
 
 
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)
 
715
{
 
716
        struct device_object *dev;
 
717
        struct dev_obj_ext *dev_obj_ext;
 
718
        int size;
 
719
 
 
720
        IOENTER("%p, %u, %p", drv_obj, dev_ext_length, dev_name);
 
721
 
 
722
        size = sizeof(*dev) + dev_ext_length + sizeof(*dev_obj_ext);
 
723
        dev = allocate_object(size, OBJECT_TYPE_DEVICE, dev_name);
 
724
        if (!dev)
 
725
                IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
 
726
        if (dev_ext_length)
 
727
                dev->dev_ext = dev + 1;
 
728
        else
 
729
                dev->dev_ext = NULL;
 
730
 
 
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;
 
736
 
 
737
        dev->type = dev_type;
 
738
        dev->flags = 0;
 
739
        dev->size = sizeof(*dev) + dev_ext_length;
 
740
        dev->ref_count = 1;
 
741
        dev->attached = NULL;
 
742
        dev->stack_count = 1;
 
743
 
 
744
        dev->drv_obj = drv_obj;
 
745
        dev->next = drv_obj->dev_obj;
 
746
        drv_obj->dev_obj = dev;
 
747
 
 
748
        dev->align_req = 1;
 
749
        dev->characteristics = dev_chars;
 
750
        dev->io_timer = NULL;
 
751
        KeInitializeEvent(&dev->lock, SynchronizationEvent, TRUE);
 
752
        dev->vpb = NULL;
 
753
 
 
754
        IOTRACE("dev: %p, ext: %p", dev, dev->dev_ext);
 
755
        *newdev = dev;
 
756
        IOEXIT(return STATUS_SUCCESS);
 
757
}
 
758
 
 
759
wstdcall NTSTATUS WIN_FUNC(IoCreateUnprotectedSymbolicLink,2)
 
760
        (struct unicode_string *link, struct unicode_string *dev_name)
 
761
{
 
762
        struct ansi_string ansi;
 
763
 
 
764
        IOENTER("%p, %p", dev_name, link);
 
765
        if (dev_name && (RtlUnicodeStringToAnsiString(&ansi, dev_name, TRUE) ==
 
766
                         STATUS_SUCCESS)) {
 
767
                IOTRACE("dev_name: %s", ansi.buf);
 
768
                RtlFreeAnsiString(&ansi);
 
769
        }
 
770
        if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) ==
 
771
                     STATUS_SUCCESS)) {
 
772
                IOTRACE("link: %s", ansi.buf);
 
773
                RtlFreeAnsiString(&ansi);
 
774
        }
 
775
//      TODO();
 
776
        IOEXIT(return STATUS_SUCCESS);
 
777
}
 
778
 
 
779
wstdcall NTSTATUS WIN_FUNC(IoCreateSymbolicLink,2)
 
780
        (struct unicode_string *link, struct unicode_string *dev_name)
 
781
{
 
782
        IOEXIT(return IoCreateUnprotectedSymbolicLink(link, dev_name));
 
783
}
 
784
 
 
785
wstdcall NTSTATUS WIN_FUNC(IoDeleteSymbolicLink,1)
 
786
        (struct unicode_string *link)
 
787
{
 
788
        struct ansi_string ansi;
 
789
 
 
790
        IOENTER("%p", link);
 
791
        if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) ==
 
792
                     STATUS_SUCCESS)) {
 
793
                IOTRACE("dev_name: %s", ansi.buf);
 
794
                RtlFreeAnsiString(&ansi);
 
795
        }
 
796
        IOEXIT(return STATUS_SUCCESS);
 
797
}
 
798
 
 
799
wstdcall void WIN_FUNC(IoDeleteDevice,1)
 
800
        (struct device_object *dev)
 
801
{
 
802
        IOENTER("%p", dev);
 
803
        if (dev == NULL)
 
804
                IOEXIT(return);
 
805
        IOTRACE("drv_obj: %p", dev->drv_obj);
 
806
        if (dev->drv_obj) {
 
807
                struct device_object *prev;
 
808
 
 
809
                prev = dev->drv_obj->dev_obj;
 
810
                IOTRACE("dev_obj: %p", prev);
 
811
                if (prev == dev)
 
812
                        dev->drv_obj->dev_obj = dev->next;
 
813
                else if (prev) {
 
814
                        while (prev->next != dev)
 
815
                                prev = prev->next;
 
816
                        prev->next = dev->next;
 
817
                }
 
818
        }
 
819
        ObDereferenceObject(dev);
 
820
        IOEXIT(return);
 
821
}
 
822
 
 
823
wstdcall void WIN_FUNC(IoDetachDevice,1)
 
824
        (struct device_object *tgt)
 
825
{
 
826
        struct device_object *tail;
 
827
 
 
828
        IOENTER("%p", tgt);
 
829
        if (!tgt)
 
830
                IOEXIT(return);
 
831
        tail = tgt->attached;
 
832
        if (!tail)
 
833
                IOEXIT(return);
 
834
        IOTRACE("tail: %p", tail);
 
835
 
 
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);
 
841
                tail->stack_count--;
 
842
        }
 
843
        spin_unlock_bh(&ntoskernel_lock);
 
844
        IOEXIT(return);
 
845
}
 
846
 
 
847
wstdcall struct device_object *WIN_FUNC(IoGetAttachedDevice,1)
 
848
        (struct device_object *dev)
 
849
{
 
850
        IOENTER("%p", dev);
 
851
        if (!dev)
 
852
                IOEXIT(return NULL);
 
853
        spin_lock_bh(&ntoskernel_lock);
 
854
        while (dev->attached)
 
855
                dev = dev->attached;
 
856
        spin_unlock_bh(&ntoskernel_lock);
 
857
        IOEXIT(return dev);
 
858
}
 
859
 
 
860
wstdcall struct device_object *WIN_FUNC(IoGetAttachedDeviceReference,1)
 
861
        (struct device_object *dev)
 
862
{
 
863
        IOENTER("%p", dev);
 
864
        if (!dev)
 
865
                IOEXIT(return NULL);
 
866
        dev = IoGetAttachedDevice(dev);
 
867
        ObReferenceObject(dev);
 
868
        IOEXIT(return dev);
 
869
}
 
870
 
 
871
wstdcall struct device_object *WIN_FUNC(IoAttachDeviceToDeviceStack,2)
 
872
        (struct device_object *src, struct device_object *tgt)
 
873
{
 
874
        struct device_object *attached;
 
875
        struct dev_obj_ext *src_dev_ext;
 
876
 
 
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);
 
882
        if (attached)
 
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,
 
889
                src->stack_count);
 
890
        IOEXIT(return attached);
 
891
}
 
892
 
 
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)
 
896
{
 
897
        struct ansi_string ansi;
 
898
        struct unicode_string unicode;
 
899
        struct wrap_device *wd;
 
900
        ULONG need;
 
901
 
 
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);
 
905
 
 
906
        wd = pdo->reserved;
 
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) {
 
917
                        *result_len = need;
 
918
                        IOEXIT(return STATUS_BUFFER_TOO_SMALL);
 
919
                }
 
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);
 
926
                }
 
927
                IOEXIT(return STATUS_SUCCESS);
 
928
        default:
 
929
                WARNING("%d not implemented", dev_property);
 
930
                IOEXIT(return STATUS_INVALID_PARAMETER_2);
 
931
        }
 
932
}
 
933
 
 
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)
 
937
{
 
938
        struct common_object_header *coh;
 
939
 
 
940
        dev_obj = NULL;
 
941
        /* TODO: access is not checked and file_obj is set to NULL */
 
942
        file_obj = 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)
 
947
                        continue;
 
948
                if (!RtlCompareUnicodeString(&coh->name, name, TRUE)) {
 
949
                        dev_obj = HEADER_TO_OBJECT(coh);
 
950
                        TRACE5("dev_obj: %p", dev_obj);
 
951
                        break;
 
952
                }
 
953
        }
 
954
        spin_unlock_bh(&ntoskernel_lock);
 
955
        if (dev_obj)
 
956
                IOEXIT(return STATUS_SUCCESS);
 
957
        else
 
958
                IOEXIT(return STATUS_OBJECT_NAME_INVALID);
 
959
}
 
960
 
 
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)
 
966
{
 
967
        IOEXIT(return state);
 
968
}
 
969
 
 
970
wstdcall NTSTATUS WIN_FUNC(PoCallDriver,2)
 
971
        (struct device_object *dev_obj, struct irp *irp)
 
972
{
 
973
        return IoCallDriver(dev_obj, irp);
 
974
}
 
975
 
 
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)
 
980
{
 
981
        struct irp *irp;
 
982
        struct io_stack_location *irp_sl;
 
983
 
 
984
        TRACE1("%p, %d, %p", dev_obj, dev_obj->stack_count, dev_obj->drv_obj);
 
985
        irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
 
986
        if (!irp)
 
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;
 
993
        else
 
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;
 
998
        *pirp = irp;
 
999
        return PoCallDriver(dev_obj, irp);
 
1000
}
 
1001
 
 
1002
wstdcall void WIN_FUNC(PoStartNextPowerIrp,1)
 
1003
        (struct irp *irp)
 
1004
{
 
1005
        IOENTER("irp = %p", irp);
 
1006
        IOEXIT(return);
 
1007
}
 
1008
 
 
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)
 
1012
{
 
1013
        TODO();
 
1014
}
 
1015
 
 
1016
wstdcall void *WIN_FUNC(IoAllocateErrorLogEntry,2)
 
1017
        (void *io_object, UCHAR entry_size)
 
1018
{
 
1019
        /* not implemented fully */
 
1020
        void *ret = kmalloc(sizeof(struct io_error_log_packet) + entry_size,
 
1021
                            irql_gfp());
 
1022
        TRACE2("%p", ret);
 
1023
        if (ret)
 
1024
                return ret + sizeof(struct io_error_log_packet);
 
1025
        else
 
1026
                return NULL;
 
1027
}
 
1028
 
 
1029
wstdcall void WIN_FUNC(IoWriteErrorLogEntry,1)
 
1030
        (void *entry)
 
1031
{
 
1032
        /* TODO: log error with codes and message */
 
1033
        ERROR("");
 
1034
}
 
1035
 
 
1036
wstdcall void WIN_FUNC(IoFreeErrorLogEntry,1)
 
1037
        (void *entry)
 
1038
{
 
1039
        TRACE2("%p", entry);
 
1040
        kfree(entry - sizeof(struct io_error_log_packet));
 
1041
}
 
1042
 
 
1043
wstdcall NTSTATUS WIN_FUNC(IoAcquireRemoveLockEx,5)
 
1044
        (struct io_remove_lock lock, void *tag, char *file, ULONG line,
 
1045
         ULONG lock_size)
 
1046
{
 
1047
        TODO();
 
1048
        IOEXIT(return STATUS_SUCCESS);
 
1049
}
 
1050
 
 
1051
wstdcall NTSTATUS WIN_FUNC(IoReleaseRemoveLockEx,3)
 
1052
        (struct io_remove_lock lock, void *tag, ULONG lock_size)
 
1053
{
 
1054
        TODO();
 
1055
        IOEXIT(return STATUS_SUCCESS);
 
1056
}
 
1057
 
 
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)
 
1061
{
 
1062
        struct ansi_string ansi;
 
1063
 
 
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);
 
1069
}
 
1070
 
 
1071
wstdcall NTSTATUS WIN_FUNC(IoSetDeviceInterfaceState,2)
 
1072
        (struct unicode_string *link, BOOLEAN enable)
 
1073
{
 
1074
        ENTER1("link: %p, enable: %d", link, enable);
 
1075
        return STATUS_SUCCESS;
 
1076
}
 
1077
 
 
1078
wstdcall NTSTATUS WIN_FUNC(IoOpenDeviceRegistryKey,4)
 
1079
        (struct device_object *dev_obj, ULONG type, ACCESS_MASK mask,
 
1080
         void **handle)
 
1081
{
 
1082
        ENTER1("dev_obj: %p", dev_obj);
 
1083
        *handle = dev_obj;
 
1084
        return STATUS_SUCCESS;
 
1085
}
 
1086
 
 
1087
wstdcall NTSTATUS WIN_FUNC(IoWMIRegistrationControl,2)
 
1088
        (struct device_object *dev_obj, ULONG action)
 
1089
{
 
1090
        ENTER2("%p, %d", dev_obj, action);
 
1091
        EXIT2(return STATUS_SUCCESS);
 
1092
}
 
1093
 
 
1094
wstdcall void WIN_FUNC(IoInvalidateDeviceRelations,2)
 
1095
        (struct device_object *dev_obj, enum device_relation_type type)
 
1096
{
 
1097
        INFO("%p, %d", dev_obj, type);
 
1098
        TODO();
 
1099
}
 
1100
 
 
1101
wstdcall void WIN_FUNC(IoInvalidateDeviceState,1)
 
1102
        (struct device_object *pdo)
 
1103
{
 
1104
        INFO("%p", pdo);
 
1105
        TODO();
 
1106
}