Subversion Repositories Kolibri OS

Rev

Rev 3555 | Rev 4265 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2465 Serge 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
164 serge 7
 
593 mikedld 8
$Revision: 3908 $
9
 
10
 
465 serge 11
DRV_COMPAT   equ  5  ;minimal required drivers version
2106 serge 12
DRV_CURRENT  equ  6  ;current drivers model version
214 serge 13
 
227 serge 14
DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT
797 serge 15
PID_KERNEL  equ 1    ;os_idle thread
227 serge 16
 
164 serge 17
 
774 Rus 18
 
164 serge 19
align 4
20
proc get_notify stdcall, p_ev:dword
21
 
22
.wait:
2434 Serge 23
        mov     ebx, [current_slot]
24
        test    dword [ebx+APPDATA.event_mask], EVENT_NOTIFY
25
        jz      @f
26
        and     dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY
27
        mov     edi, [p_ev]
28
        mov     dword [edi], EV_INTR
29
        mov     eax, [ebx+APPDATA.event]
30
        mov     dword [edi+4], eax
31
        ret
164 serge 32
@@:
2434 Serge 33
        call    change_task
34
        jmp     .wait
164 serge 35
endp
36
 
37
 
2434 Serge 38
handle     equ  IOCTL.handle
39
io_code    equ  IOCTL.io_code
40
input      equ  IOCTL.input
41
inp_size   equ  IOCTL.inp_size
42
output     equ  IOCTL.output
43
out_size   equ  IOCTL.out_size
164 serge 44
 
672 hidnplayr 45
 
164 serge 46
align 4
47
proc srv_handler stdcall, ioctl:dword
2434 Serge 48
        mov     esi, [ioctl]
49
        test    esi, esi
50
        jz      .err
164 serge 51
 
2434 Serge 52
        mov     edi, [esi+handle]
53
        cmp     [edi+SRV.magic], ' SRV'
54
        jne     .fail
164 serge 55
 
2434 Serge 56
        cmp     [edi+SRV.size], sizeof.SRV
57
        jne     .fail
164 serge 58
 
3555 Serge 59
;        stdcall [edi+SRV.srv_proc], esi
60
        mov     eax, [edi+SRV.srv_proc]
61
        test    eax, eax
62
        jz      .fail
63
        stdcall eax, esi
2434 Serge 64
        ret
164 serge 65
.fail:
2434 Serge 66
        xor     eax, eax
67
        not     eax
68
        mov     [esi+output], eax
69
        mov     [esi+out_size], 4
70
        ret
164 serge 71
.err:
2434 Serge 72
        xor     eax, eax
73
        not     eax
74
        ret
164 serge 75
endp
76
 
377 serge 77
; param
1345 Lrz 78
;  ecx= io_control
377 serge 79
;
80
; retval
81
;  eax= error code
82
 
164 serge 83
align 4
377 serge 84
srv_handlerEx:
2434 Serge 85
        cmp     ecx, OS_BASE
86
        jae     .fail
164 serge 87
 
2434 Serge 88
        mov     eax, [ecx+handle]
89
        cmp     [eax+SRV.magic], ' SRV'
90
        jne     .fail
164 serge 91
 
2434 Serge 92
        cmp     [eax+SRV.size], sizeof.SRV
93
        jne     .fail
164 serge 94
 
3555 Serge 95
;        stdcall [eax+SRV.srv_proc], ecx
96
        mov     eax, [eax+SRV.srv_proc]
97
        test    eax, eax
98
        jz      .fail
99
        stdcall eax, ecx
2434 Serge 100
        ret
164 serge 101
.fail:
2434 Serge 102
        or      eax, -1
103
        ret
164 serge 104
 
105
restore  handle
106
restore  io_code
107
restore  input
108
restore  inp_size
109
restore  output
110
restore  out_size
111
 
112
align 4
113
proc get_service stdcall, sz_name:dword
2434 Serge 114
        mov     eax, [sz_name]
115
        test    eax, eax
116
        jnz     @F
117
        ret
164 serge 118
@@:
2434 Serge 119
        mov     edx, [srv.fd]
188 serge 120
@@:
2434 Serge 121
        cmp     edx, srv.fd-SRV.fd
122
        je      .not_load
278 serge 123
 
2434 Serge 124
        stdcall strncmp, edx, [sz_name], 16
125
        test    eax, eax
126
        je      .ok
164 serge 127
 
2434 Serge 128
        mov     edx, [edx+SRV.fd]
129
        jmp     @B
164 serge 130
.not_load:
2434 Serge 131
        pop     ebp
132
        jmp     load_driver
164 serge 133
.ok:
2434 Serge 134
        mov     eax, edx
135
        ret
164 serge 136
endp
137
 
3555 Serge 138
reg_service:
139
        xor     eax, eax
140
        mov     ecx, [esp+8]
141
        jecxz   .nothing
142
        push    sizeof.SRV
143
        push    ecx
144
        pushd   [esp+12]
145
        call    reg_service_ex
146
.nothing:
147
        ret     8
164 serge 148
 
3555 Serge 149
reg_usb_driver:
150
        push    sizeof.USBSRV
151
        pushd   [esp+12]
152
        pushd   [esp+12]
153
        call    reg_service_ex
154
        test    eax, eax
155
        jz      .nothing
156
        mov     ecx, [esp+12]
157
        mov     [eax+USBSRV.usb_func], ecx
158
.nothing:
159
        ret     12
160
 
161
proc reg_service_ex stdcall, name:dword, handler:dword, srvsize:dword
162
 
2434 Serge 163
        push    ebx
164 serge 164
 
2434 Serge 165
        xor     eax, eax
819 serge 166
 
2434 Serge 167
        cmp     [name], eax
168
        je      .fail
740 serge 169
 
3555 Serge 170
;        cmp     [handler], eax
171
;        je      .fail
740 serge 172
 
3555 Serge 173
        mov     eax, [srvsize]
2434 Serge 174
        call    malloc
175
        test    eax, eax
176
        jz      .fail
164 serge 177
 
2434 Serge 178
        push    esi
179
        push    edi
180
        mov     edi, eax
181
        mov     esi, [name]
182
        movsd
183
        movsd
184
        movsd
185
        movsd
186
        pop     edi
187
        pop     esi
164 serge 188
 
2434 Serge 189
        mov     [eax+SRV.magic], ' SRV'
190
        mov     [eax+SRV.size], sizeof.SRV
278 serge 191
 
2434 Serge 192
        mov     ebx, srv.fd-SRV.fd
193
        mov     edx, [ebx+SRV.fd]
194
        mov     [eax+SRV.fd], edx
195
        mov     [eax+SRV.bk], ebx
196
        mov     [ebx+SRV.fd], eax
197
        mov     [edx+SRV.bk], eax
278 serge 198
 
2434 Serge 199
        mov     ecx, [handler]
200
        mov     [eax+SRV.srv_proc], ecx
201
        pop     ebx
202
        ret
164 serge 203
.fail:
2434 Serge 204
        xor     eax, eax
205
        pop     ebx
206
        ret
740 serge 207
endp
164 serge 208
 
209
align 4
210
proc get_proc stdcall, exp:dword, sz_name:dword
211
 
2434 Serge 212
        mov     edx, [exp]
164 serge 213
.next:
2434 Serge 214
        mov     eax, [edx]
215
        test    eax, eax
216
        jz      .end
164 serge 217
 
2434 Serge 218
        push    edx
219
        stdcall strncmp, eax, [sz_name], 16
220
        pop     edx
221
        test    eax, eax
222
        jz      .ok
164 serge 223
 
2434 Serge 224
        add     edx, 8
225
        jmp     .next
164 serge 226
.ok:
2434 Serge 227
        mov     eax, [edx+4]
164 serge 228
.end:
2434 Serge 229
        ret
164 serge 230
endp
231
 
232
align 4
233
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
234
 
235
@@:
2434 Serge 236
        stdcall strncmp, [pSym], [sz_sym], 8
237
        test    eax, eax
238
        jz      .ok
239
        add     [pSym], 18
240
        dec     [count]
241
        jnz     @b
242
        xor     eax, eax
243
        ret
164 serge 244
.ok:
2434 Serge 245
        mov     eax, [pSym]
246
        mov     eax, [eax+8]
247
        ret
164 serge 248
endp
249
 
250
align 4
188 serge 251
proc get_curr_task
2434 Serge 252
        mov     eax, [CURRENT_TASK]
253
        shl     eax, 8
254
        ret
188 serge 255
endp
164 serge 256
 
188 serge 257
align 4
258
proc get_fileinfo stdcall, file_name:dword, info:dword
2434 Serge 259
           locals
260
             cmd     dd ?
261
             offset  dd ?
262
                     dd ?
263
             count   dd ?
264
             buff    dd ?
265
                     db ?
266
             name    dd ?
267
           endl
164 serge 268
 
2434 Serge 269
        xor     eax, eax
270
        mov     ebx, [file_name]
271
        mov     ecx, [info]
164 serge 272
 
2434 Serge 273
        mov     [cmd], 5
274
        mov     [offset], eax
275
        mov     [offset+4], eax
276
        mov     [count], eax
277
        mov     [buff], ecx
278
        mov     byte [buff+4], al
279
        mov     [name], ebx
164 serge 280
 
2434 Serge 281
        mov     eax, 70
282
        lea     ebx, [cmd]
283
        int     0x40
284
        ret
188 serge 285
endp
164 serge 286
 
188 serge 287
align 4
288
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\
2434 Serge 289
                                     bytes:dword
290
           locals
291
             cmd     dd ?
292
             offset  dd ?
293
                     dd ?
294
             count   dd ?
295
             buff    dd ?
296
                     db ?
297
             name    dd ?
298
           endl
164 serge 299
 
2434 Serge 300
        xor     eax, eax
301
        mov     ebx, [file_name]
302
        mov     ecx, [off]
303
        mov     edx, [bytes]
304
        mov     esi, [buffer]
164 serge 305
 
2434 Serge 306
        mov     [cmd], eax
307
        mov     [offset], ecx
308
        mov     [offset+4], eax
309
        mov     [count], edx
310
        mov     [buff], esi
311
        mov     byte [buff+4], al
312
        mov     [name], ebx
188 serge 313
 
2434 Serge 314
        pushad
315
        lea     ebx, [cmd]
3500 Serge 316
        call    file_system_lfn_protected
2434 Serge 317
        popad
318
        ret
188 serge 319
endp
320
 
363 serge 321
; description
322
;  allocate kernel memory and loads the specified file
323
;
324
; param
325
;  file_name= full path to file
326
;
327
; retval
328
;  eax= file image in kernel memory
329
;  ebx= size of file
330
;
331
; warging
332
;  You mast call kernel_free() to delete each file
333
;  loaded by the load_file() function
334
 
188 serge 335
align 4
336
proc load_file stdcall, file_name:dword
2434 Serge 337
           locals
338
             attr       dd ?
339
             flags      dd ?
340
             cr_time    dd ?
341
             cr_date    dd ?
342
             acc_time   dd ?
343
             acc_date   dd ?
344
             mod_time   dd ?
345
             mod_date   dd ?
346
             file_size  dd ?
188 serge 347
 
2434 Serge 348
             file       dd ?
349
             file2      dd ?
350
           endl
188 serge 351
 
2434 Serge 352
        push    esi
353
        push    edi
662 serge 354
 
2434 Serge 355
        lea     eax, [attr]
356
        stdcall get_fileinfo, [file_name], eax
357
        test    eax, eax
358
        jnz     .fail
164 serge 359
 
2434 Serge 360
        mov     eax, [file_size]
361
        cmp     eax, 1024*1024*16
362
        ja      .fail
206 serge 363
 
2434 Serge 364
        stdcall kernel_alloc, [file_size]
365
        mov     [file], eax
366
        test    eax, eax
367
        jz      .fail
164 serge 368
 
2434 Serge 369
        stdcall read_file, [file_name], eax, dword 0, [file_size]
370
        cmp     ebx, [file_size]
371
        jne     .cleanup
211 serge 372
 
2434 Serge 373
        mov     eax, [file]
374
        cmp     dword [eax], 0x4B43504B
375
        jne     .exit
376
        mov     ebx, [eax+4]
377
        mov     [file_size], ebx
378
        stdcall kernel_alloc, ebx
211 serge 379
 
2434 Serge 380
        test    eax, eax
381
        jz      .cleanup
211 serge 382
 
2434 Serge 383
        mov     [file2], eax
2987 Serge 384
 
385
        pushad
386
        mov     ecx, unpack_mutex
387
        call    mutex_lock
388
        popad
389
 
2434 Serge 390
        stdcall unpack, [file], eax
2987 Serge 391
 
392
        pushad
393
        mov     ecx, unpack_mutex
394
        call    mutex_unlock
395
        popad
396
 
2434 Serge 397
        stdcall kernel_free, [file]
398
        mov     eax, [file2]
399
        mov     ebx, [file_size]
211 serge 400
.exit:
2434 Serge 401
        push    eax
402
        lea     edi, [eax+ebx]    ;cleanup remain space
403
        mov     ecx, 4096         ;from file end
404
        and     ebx, 4095
405
        jz      @f
406
        sub     ecx, ebx
407
        xor     eax, eax
408
        cld
409
        rep stosb
521 diamond 410
@@:
2434 Serge 411
        mov     ebx, [file_size]
412
        pop     eax
413
        pop     edi
414
        pop     esi
415
        ret
188 serge 416
.cleanup:
2434 Serge 417
        stdcall kernel_free, [file]
188 serge 418
.fail:
2434 Serge 419
        xor     eax, eax
420
        xor     ebx, ebx
421
        pop     edi
422
        pop     esi
423
        ret
188 serge 424
endp
164 serge 425
 
3908 Serge 426
; description
427
;  allocate user memory and loads the specified file
428
;
429
; param
430
;  file_name= path to file
431
;
432
; retval
433
;  eax= file image in user memory
434
;  ebx= size of file
435
;
436
; warging
437
;  You mast call kernel_free() to delete each file
438
;  loaded by the load_file() function
439
 
440
align 4
441
proc load_file_umode stdcall, file_name:dword
442
           locals
443
             attr       dd ?
444
             flags      dd ?
445
             cr_time    dd ?
446
             cr_date    dd ?
447
             acc_time   dd ?
448
             acc_date   dd ?
449
             mod_time   dd ?
450
             mod_date   dd ?
451
             file_size  dd ?
452
 
453
             km_file    dd ?
454
             um_file    dd ?
455
           endl
456
 
457
        push    esi
458
        push    edi
459
        push    ebx
460
 
461
 
462
        lea     eax, [attr]
463
        stdcall get_fileinfo, [file_name], eax   ;find file and get info
464
        test    eax, eax
465
        jnz     .err_1
466
 
467
        mov     eax, [file_size]
468
        cmp     eax, 1024*1024*16                ;to be enough for anybody (c)
469
        ja      .err_1
470
                                                 ;it is very likely that the file is packed
471
        stdcall kernel_alloc, [file_size]        ;with kpack, so allocate memory from kernel heap
472
        mov     [km_file], eax
473
        test    eax, eax
474
        jz      .err_1
475
 
476
        stdcall read_file, [file_name], eax, dword 0, [file_size]
477
        cmp     ebx, [file_size]
478
 
479
        jne     .err_2
480
 
481
        mov     eax, [km_file]
482
        cmp     dword [eax], 0x4B43504B          ; check kpack signature
483
        jne     .raw_file
484
 
485
        mov     ebx, [eax+4]                     ;get real size of file
486
        mov     [file_size], ebx
487
        stdcall user_alloc, ebx                  ;and allocate memory from user heap
488
        mov     [um_file], eax
489
        test    eax, eax
490
        jz      .err_2
491
 
492
        pushad
493
        mov     ecx, unpack_mutex
494
        call    mutex_lock
495
 
496
        stdcall unpack, [km_file], [um_file]
497
 
498
        mov     ecx, unpack_mutex
499
        call    mutex_unlock
500
        popad
501
 
502
        stdcall kernel_free, [km_file]           ;we don't need packed file anymore
503
.exit:
504
        mov     eax, [um_file]
505
        mov     edx, [file_size]
506
 
507
        pop     ebx
508
        pop     edi
509
        pop     esi
510
        ret
511
 
512
 
513
.raw_file:                                       ; sometimes we load unpacked file
514
        stdcall user_alloc, ebx                  ; allocate space from user heap
515
        mov     [um_file], eax
516
 
517
        test    eax, eax
518
        jz      .err_2
519
 
520
        shr     eax, 10                          ; and remap pages.
521
 
522
        mov     ecx, [file_size]
523
        add     ecx, 4095
524
        shr     ecx, 12
525
 
526
        mov     esi, [km_file]
527
        shr     esi, 10
528
        add     esi, page_tabs
529
 
530
        lea     edi, [page_tabs+eax]
531
 
532
        cld
533
@@:
534
        lodsd
535
        and     eax, 0xFFFFF000
536
        or      eax, PG_USER
537
        stosd
538
        loop    @B
539
 
540
        stdcall free_kernel_space, [km_file]     ; release allocated kernel space
541
        jmp     .exit                            ; physical pages still in use
542
 
543
.err_2:
544
        stdcall kernel_free, [km_file]
545
.err_1:
546
        xor     eax, eax
547
        xor     edx, edx
548
 
549
        pop     ebx
550
        pop     edi
551
        pop     esi
552
        ret
553
endp
554
 
555
 
2987 Serge 556
uglobal
188 serge 557
align 4
2987 Serge 558
unpack_mutex MUTEX
559
endg
560
 
561
align 4
3908 Serge 562
proc get_proc_ex stdcall uses ebx esi, proc_name:dword, imports:dword
563
        mov     ebx, [imports]
564
        test    ebx, ebx
565
        jz      .end
566
        xor     esi, esi
188 serge 567
.look_up:
164 serge 568
 
3908 Serge 569
        mov     eax, [ebx+32]
570
        mov     eax, [OS_BASE+eax+esi*4]
571
        add     eax, OS_BASE
2434 Serge 572
        stdcall strncmp, eax, [proc_name], 256
573
        test    eax, eax
574
        jz      .ok
164 serge 575
 
3908 Serge 576
        inc     esi
577
        cmp     esi, [ebx+24]
578
        jb      .look_up
188 serge 579
.end:
2434 Serge 580
        xor     eax, eax
581
        ret
3908 Serge 582
.ok:
583
        mov     eax, [ebx+28]
584
        mov     eax, [OS_BASE+eax+esi*4]
585
        add     eax, OS_BASE
586
        ret
188 serge 587
endp
164 serge 588
 
188 serge 589
align 4
1289 diamond 590
proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
2434 Serge 591
                      sym_count:dword, strings:dword, imports:dword
592
           locals
593
             retval dd ?
594
           endl
164 serge 595
 
2434 Serge 596
        mov     edi, [symbols]
597
        mov     [retval], 1
188 serge 598
.fix:
2434 Serge 599
        movzx   ebx, [edi+COFF_SYM.SectionNumber]
600
        test    ebx, ebx
601
        jnz     .internal
602
        mov     eax, dword [edi+COFF_SYM.Name]
603
        test    eax, eax
604
        jnz     @F
164 serge 605
 
2434 Serge 606
        mov     edi, [edi+4]
607
        add     edi, [strings]
188 serge 608
@@:
2434 Serge 609
        push    edi
610
        stdcall get_proc_ex, edi, [imports]
611
        pop     edi
164 serge 612
 
2434 Serge 613
        xor     ebx, ebx
614
        test    eax, eax
615
        jnz     @F
164 serge 616
 
2434 Serge 617
        mov     esi, msg_unresolved
618
        call    sys_msg_board_str
619
        mov     esi, edi
620
        call    sys_msg_board_str
621
        mov     esi, msg_CR
622
        call    sys_msg_board_str
164 serge 623
 
2434 Serge 624
        mov     [retval], 0
188 serge 625
@@:
2434 Serge 626
        mov     edi, [symbols]
627
        mov     [edi+COFF_SYM.Value], eax
628
        jmp     .next
188 serge 629
.internal:
2434 Serge 630
        cmp     bx, -1
631
        je      .next
632
        cmp     bx, -2
633
        je      .next
541 serge 634
 
2434 Serge 635
        dec     ebx
636
        shl     ebx, 3
637
        lea     ebx, [ebx+ebx*4]
638
        add     ebx, [sec]
188 serge 639
 
2434 Serge 640
        mov     eax, [ebx+COFF_SECTION.VirtualAddress]
641
        add     [edi+COFF_SYM.Value], eax
188 serge 642
.next:
2434 Serge 643
        add     edi, sizeof.COFF_SYM
644
        mov     [symbols], edi
645
        dec     [sym_count]
646
        jnz     .fix
647
        mov     eax, [retval]
648
        ret
164 serge 649
endp
650
 
651
align 4
1289 diamond 652
proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
2434 Serge 653
        delta:dword
654
           locals
655
             n_sec     dd ?
656
           endl
164 serge 657
 
2434 Serge 658
        mov     eax, [coff]
659
        movzx   ebx, [eax+COFF_HEADER.nSections]
660
        mov     [n_sec], ebx
661
        lea     esi, [eax+20]
188 serge 662
.fix_sec:
2434 Serge 663
        mov     edi, [esi+COFF_SECTION.PtrReloc]
664
        add     edi, [coff]
164 serge 665
 
2434 Serge 666
        movzx   ecx, [esi+COFF_SECTION.NumReloc]
667
        test    ecx, ecx
668
        jz      .next
1289 diamond 669
.reloc_loop:
2434 Serge 670
        mov     ebx, [edi+COFF_RELOC.SymIndex]
671
        add     ebx, ebx
672
        lea     ebx, [ebx+ebx*8]
673
        add     ebx, [sym]
164 serge 674
 
2434 Serge 675
        mov     edx, [ebx+COFF_SYM.Value]
164 serge 676
 
2434 Serge 677
        cmp     [edi+COFF_RELOC.Type], 6
678
        je      .dir_32
164 serge 679
 
2434 Serge 680
        cmp     [edi+COFF_RELOC.Type], 20
681
        jne     .next_reloc
188 serge 682
.rel_32:
2434 Serge 683
        mov     eax, [edi+COFF_RELOC.VirtualAddress]
684
        add     eax, [esi+COFF_SECTION.VirtualAddress]
685
        sub     edx, eax
686
        sub     edx, 4
687
        jmp     .fix
188 serge 688
.dir_32:
2434 Serge 689
        mov     eax, [edi+COFF_RELOC.VirtualAddress]
690
        add     eax, [esi+COFF_SECTION.VirtualAddress]
188 serge 691
.fix:
2434 Serge 692
        add     eax, [delta]
693
        add     [eax], edx
1289 diamond 694
.next_reloc:
2434 Serge 695
        add     edi, 10
696
        dec     ecx
697
        jnz     .reloc_loop
188 serge 698
.next:
2434 Serge 699
        add     esi, sizeof.COFF_SECTION
700
        dec     [n_sec]
701
        jnz     .fix_sec
164 serge 702
.exit:
2434 Serge 703
        ret
164 serge 704
endp
705
 
2106 serge 706
align 4
1289 diamond 707
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
2434 Serge 708
        delta:dword
709
           locals
710
             n_sec     dd ?
711
           endl
1289 diamond 712
 
2434 Serge 713
        mov     eax, [coff]
714
        movzx   ebx, [eax+COFF_HEADER.nSections]
715
        mov     [n_sec], ebx
716
        lea     esi, [eax+20]
717
        mov     edx, [delta]
1289 diamond 718
.fix_sec:
2434 Serge 719
        mov     edi, [esi+COFF_SECTION.PtrReloc]
720
        add     edi, [coff]
1289 diamond 721
 
2434 Serge 722
        movzx   ecx, [esi+COFF_SECTION.NumReloc]
723
        test    ecx, ecx
724
        jz      .next
1289 diamond 725
.reloc_loop:
2434 Serge 726
        cmp     [edi+COFF_RELOC.Type], 6
727
        jne     .next_reloc
1289 diamond 728
.dir_32:
2434 Serge 729
        mov     eax, [edi+COFF_RELOC.VirtualAddress]
730
        add     eax, [esi+COFF_SECTION.VirtualAddress]
731
        add     [eax+edx], edx
1289 diamond 732
.next_reloc:
2434 Serge 733
        add     edi, 10
734
        dec     ecx
735
        jnz     .reloc_loop
1289 diamond 736
.next:
2434 Serge 737
        add     esi, sizeof.COFF_SECTION
738
        dec     [n_sec]
739
        jnz     .fix_sec
1289 diamond 740
.exit:
2434 Serge 741
        ret
1289 diamond 742
endp
743
 
188 serge 744
align 4
346 diamond 745
proc load_driver stdcall, driver_name:dword
2434 Serge 746
           locals
747
             coff      dd ?
748
             sym       dd ?
749
             strings   dd ?
750
             img_size  dd ?
751
             img_base  dd ?
752
             start     dd ?
188 serge 753
 
2434 Serge 754
             file_name rb 13+16+4+1      ; '/sys/drivers/.obj'
755
           endl
188 serge 756
 
2434 Serge 757
        lea     edx, [file_name]
758
        mov     dword [edx], '/sys'
759
        mov     dword [edx+4], '/dri'
760
        mov     dword [edx+8], 'vers'
761
        mov     byte [edx+12], '/'
762
        mov     esi, [driver_name]
1018 diamond 763
.redo:
2434 Serge 764
        lea     edx, [file_name]
765
        lea     edi, [edx+13]
766
        mov     ecx, 16
346 diamond 767
@@:
2434 Serge 768
        lodsb
769
        test    al, al
770
        jz      @f
771
        stosb
772
        loop    @b
346 diamond 773
@@:
2434 Serge 774
        mov     dword [edi], '.obj'
775
        mov     byte [edi+4], 0
776
        stdcall load_file, edx
214 serge 777
 
2434 Serge 778
        test    eax, eax
779
        jz      .exit
188 serge 780
 
2434 Serge 781
        mov     [coff], eax
188 serge 782
 
2434 Serge 783
        movzx   ecx, [eax+COFF_HEADER.nSections]
784
        xor     ebx, ebx
188 serge 785
 
2434 Serge 786
        lea     edx, [eax+20]
188 serge 787
@@:
2434 Serge 788
        add     ebx, [edx+COFF_SECTION.SizeOfRawData]
789
        add     ebx, 15
790
        and     ebx, not 15
791
        add     edx, sizeof.COFF_SECTION
792
        dec     ecx
793
        jnz     @B
794
        mov     [img_size], ebx
188 serge 795
 
2434 Serge 796
        stdcall kernel_alloc, ebx
797
        test    eax, eax
798
        jz      .fail
799
        mov     [img_base], eax
188 serge 800
 
2434 Serge 801
        mov     edi, eax
802
        xor     eax, eax
803
        mov     ecx, [img_size]
804
        add     ecx, 4095
805
        and     ecx, not 4095
806
        shr     ecx, 2
807
        cld
808
        rep stosd
188 serge 809
 
2434 Serge 810
        mov     edx, [coff]
811
        movzx   ebx, [edx+COFF_HEADER.nSections]
812
        mov     edi, [img_base]
813
        lea     eax, [edx+20]
188 serge 814
@@:
2434 Serge 815
        mov     [eax+COFF_SECTION.VirtualAddress], edi
816
        mov     esi, [eax+COFF_SECTION.PtrRawData]
817
        test    esi, esi
818
        jnz     .copy
819
        add     edi, [eax+COFF_SECTION.SizeOfRawData]
820
        jmp     .next
188 serge 821
.copy:
2434 Serge 822
        add     esi, edx
823
        mov     ecx, [eax+COFF_SECTION.SizeOfRawData]
824
        cld
825
        rep movsb
188 serge 826
.next:
2434 Serge 827
        add     edi, 15
828
        and     edi, not 15
829
        add     eax, sizeof.COFF_SECTION
830
        dec     ebx
831
        jnz     @B
188 serge 832
 
2434 Serge 833
        mov     ebx, [edx+COFF_HEADER.pSymTable]
834
        add     ebx, edx
835
        mov     [sym], ebx
836
        mov     ecx, [edx+COFF_HEADER.nSymbols]
837
        add     ecx, ecx
838
        lea     ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE
839
        add     ecx, [sym]
840
        mov     [strings], ecx
188 serge 841
 
2434 Serge 842
        lea     eax, [edx+20]
188 serge 843
 
2434 Serge 844
        stdcall fix_coff_symbols, eax, [sym], [edx+COFF_HEADER.nSymbols], \
3908 Serge 845
                [strings], __exports
2434 Serge 846
        test    eax, eax
847
        jz      .link_fail
188 serge 848
 
2434 Serge 849
        mov     ebx, [coff]
850
        stdcall fix_coff_relocs, ebx, [sym], 0
188 serge 851
 
2434 Serge 852
        stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szVersion
853
        test    eax, eax
854
        jz      .link_fail
227 serge 855
 
2434 Serge 856
        mov     eax, [eax]
857
        shr     eax, 16
858
        cmp     eax, DRV_COMPAT
859
        jb      .ver_fail
227 serge 860
 
2434 Serge 861
        cmp     eax, DRV_CURRENT
862
        ja      .ver_fail
227 serge 863
 
2434 Serge 864
        mov     ebx, [coff]
865
        stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szSTART
866
        mov     [start], eax
188 serge 867
 
2434 Serge 868
        stdcall kernel_free, [coff]
188 serge 869
 
2434 Serge 870
        mov     ebx, [start]
871
        stdcall ebx, DRV_ENTRY
872
        test    eax, eax
873
        jnz     .ok
188 serge 874
 
2434 Serge 875
        stdcall kernel_free, [img_base]
3232 Serge 876
 
2434 Serge 877
        xor     eax, eax
878
        ret
188 serge 879
.ok:
2434 Serge 880
        mov     ebx, [img_base]
881
        mov     [eax+SRV.base], ebx
882
        mov     ecx, [start]
883
        mov     [eax+SRV.entry], ecx
884
        ret
227 serge 885
 
886
.ver_fail:
2434 Serge 887
        mov     esi, msg_CR
888
        call    sys_msg_board_str
889
        mov     esi, [driver_name]
890
        call    sys_msg_board_str
891
        mov     esi, msg_CR
892
        call    sys_msg_board_str
893
        mov     esi, msg_version
894
        call    sys_msg_board_str
895
        mov     esi, msg_www
896
        call    sys_msg_board_str
897
        jmp     .cleanup
227 serge 898
 
899
.link_fail:
2434 Serge 900
        mov     esi, msg_module
901
        call    sys_msg_board_str
902
        mov     esi, [driver_name]
903
        call    sys_msg_board_str
904
        mov     esi, msg_CR
905
        call    sys_msg_board_str
227 serge 906
.cleanup:
2434 Serge 907
        stdcall kernel_free, [img_base]
188 serge 908
.fail:
2434 Serge 909
        stdcall kernel_free, [coff]
227 serge 910
.exit:
2434 Serge 911
        xor     eax, eax
912
        ret
164 serge 913
endp
914
 
1296 diamond 915
; in: edx -> COFF_SECTION struct
916
; out: eax = alignment as mask for bits to drop
917
coff_get_align:
918
; Rules:
919
; - if alignment is not given, use default = 4K;
920
; - if alignment is given and is no more than 4K, use it;
921
; - if alignment is more than 4K, revert to 4K.
2434 Serge 922
        push    ecx
923
        mov     cl, byte [edx+COFF_SECTION.Characteristics+2]
924
        mov     eax, 1
925
        shr     cl, 4
926
        dec     cl
927
        js      .default
928
        cmp     cl, 12
929
        jbe     @f
1296 diamond 930
.default:
2434 Serge 931
        mov     cl, 12
1296 diamond 932
@@:
2434 Serge 933
        shl     eax, cl
934
        pop     ecx
935
        dec     eax
936
        ret
1296 diamond 937
 
198 serge 938
align 4
939
proc load_library stdcall, file_name:dword
2434 Serge 940
           locals
941
             fullname  rb 260
942
             fileinfo  rb 40
943
             coff      dd ?
944
             img_base  dd ?
945
           endl
198 serge 946
 
1289 diamond 947
; resolve file name
2434 Serge 948
        mov     ebx, [file_name]
949
        lea     edi, [fullname+1]
950
        mov     byte [edi-1], '/'
951
        stdcall get_full_file_name, edi, 259
952
        test    al, al
953
        jz      .fail
1289 diamond 954
 
955
; scan for required DLL in list of already loaded for this process,
956
; ignore timestamp
3908 Serge 957
        cli
958
 
2434 Serge 959
        mov     esi, [CURRENT_TASK]
960
        shl     esi, 8
961
        lea     edi, [fullname]
962
        mov     ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr]
963
        test    ebx, ebx
964
        jz      .not_in_process
965
        mov     esi, [ebx+HDLL.fd]
1289 diamond 966
.scan_in_process:
2434 Serge 967
        cmp     esi, ebx
968
        jz      .not_in_process
969
        mov     eax, [esi+HDLL.parent]
970
        add     eax, DLLDESCR.name
971
        stdcall strncmp, eax, edi, -1
972
        test    eax, eax
973
        jnz     .next_in_process
1289 diamond 974
; simple variant: load DLL which is already loaded in this process
975
; just increment reference counters and return address of exports table
2434 Serge 976
        inc     [esi+HDLL.refcount]
977
        mov     ecx, [esi+HDLL.parent]
978
        inc     [ecx+DLLDESCR.refcount]
979
        mov     eax, [ecx+DLLDESCR.exports]
980
        sub     eax, [ecx+DLLDESCR.defaultbase]
981
        add     eax, [esi+HDLL.base]
3908 Serge 982
        sti
2434 Serge 983
        ret
1289 diamond 984
.next_in_process:
2434 Serge 985
        mov     esi, [esi+HDLL.fd]
986
        jmp     .scan_in_process
1289 diamond 987
.not_in_process:
988
 
989
; scan in full list, compare timestamp
3908 Serge 990
        sti
2434 Serge 991
        lea     eax, [fileinfo]
992
        stdcall get_fileinfo, edi, eax
993
        test    eax, eax
994
        jnz     .fail
3908 Serge 995
        cli
2434 Serge 996
        mov     esi, [dll_list.fd]
1289 diamond 997
.scan_for_dlls:
2434 Serge 998
        cmp     esi, dll_list
999
        jz      .load_new
1000
        lea     eax, [esi+DLLDESCR.name]
1001
        stdcall strncmp, eax, edi, -1
1002
        test    eax, eax
1003
        jnz     .continue_scan
1289 diamond 1004
.test_prev_dll:
2434 Serge 1005
        mov     eax, dword [fileinfo+24]; last modified time
1006
        mov     edx, dword [fileinfo+28]; last modified date
1007
        cmp     dword [esi+DLLDESCR.timestamp], eax
1008
        jnz     .continue_scan
1009
        cmp     dword [esi+DLLDESCR.timestamp+4], edx
1010
        jz      .dll_already_loaded
1289 diamond 1011
.continue_scan:
2434 Serge 1012
        mov     esi, [esi+DLLDESCR.fd]
1013
        jmp     .scan_for_dlls
1289 diamond 1014
 
1015
; new DLL
1016
.load_new:
3908 Serge 1017
        sti
1289 diamond 1018
; load file
2434 Serge 1019
        stdcall load_file, edi
1020
        test    eax, eax
1021
        jz      .fail
1022
        mov     [coff], eax
1023
        mov     dword [fileinfo+32], ebx
198 serge 1024
 
1289 diamond 1025
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
2434 Serge 1026
        mov     esi, edi
1027
        mov     ecx, -1
1028
        xor     eax, eax
1029
        repnz scasb
1030
        not     ecx
1031
        lea     eax, [ecx+sizeof.DLLDESCR]
1032
        push    ecx
1033
        call    malloc
1034
        pop     ecx
1035
        test    eax, eax
1036
        jz      .fail_and_free_coff
1289 diamond 1037
; save timestamp
2434 Serge 1038
        lea     edi, [eax+DLLDESCR.name]
1039
        rep movsb
1040
        mov     esi, eax
1041
        mov     eax, dword [fileinfo+24]
1042
        mov     dword [esi+DLLDESCR.timestamp], eax
1043
        mov     eax, dword [fileinfo+28]
1044
        mov     dword [esi+DLLDESCR.timestamp+4], eax
1289 diamond 1045
 
1046
; calculate size of loaded DLL
2434 Serge 1047
        mov     edx, [coff]
1048
        movzx   ecx, [edx+COFF_HEADER.nSections]
1049
        xor     ebx, ebx
198 serge 1050
 
2434 Serge 1051
        add     edx, 20
198 serge 1052
@@:
2434 Serge 1053
        call    coff_get_align
1054
        add     ebx, eax
1055
        not     eax
1056
        and     ebx, eax
1057
        add     ebx, [edx+COFF_SECTION.SizeOfRawData]
1058
        add     edx, sizeof.COFF_SECTION
1059
        dec     ecx
1060
        jnz     @B
1289 diamond 1061
; it must be nonzero and not too big
2434 Serge 1062
        mov     [esi+DLLDESCR.size], ebx
1063
        test    ebx, ebx
1064
        jz      .fail_and_free_dll
1065
        cmp     ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
1066
        ja      .fail_and_free_dll
1289 diamond 1067
; allocate memory for kernel-side image
2434 Serge 1068
        stdcall kernel_alloc, ebx
1069
        test    eax, eax
1070
        jz      .fail_and_free_dll
1071
        mov     [esi+DLLDESCR.data], eax
1289 diamond 1072
; calculate preferred base address
2434 Serge 1073
        add     ebx, 0x1FFF
1074
        and     ebx, not 0xFFF
1075
        mov     ecx, [dll_cur_addr]
1076
        lea     edx, [ecx+ebx]
1077
        cmp     edx, MAX_DEFAULT_DLL_ADDR
1078
        jb      @f
1079
        mov     ecx, MIN_DEFAULT_DLL_ADDR
1080
        lea     edx, [ecx+ebx]
1289 diamond 1081
@@:
2434 Serge 1082
        mov     [esi+DLLDESCR.defaultbase], ecx
1083
        mov     [dll_cur_addr], edx
198 serge 1084
 
1289 diamond 1085
; copy sections and set correct values for VirtualAddress'es in headers
2434 Serge 1086
        push    esi
1087
        mov     edx, [coff]
1088
        movzx   ebx, [edx+COFF_HEADER.nSections]
1089
        mov     edi, eax
1090
        add     edx, 20
1091
        cld
198 serge 1092
@@:
2434 Serge 1093
        call    coff_get_align
1094
        add     ecx, eax
1095
        add     edi, eax
1096
        not     eax
1097
        and     ecx, eax
1098
        and     edi, eax
1099
        mov     [edx+COFF_SECTION.VirtualAddress], ecx
1100
        add     ecx, [edx+COFF_SECTION.SizeOfRawData]
1101
        mov     esi, [edx+COFF_SECTION.PtrRawData]
1102
        push    ecx
1103
        mov     ecx, [edx+COFF_SECTION.SizeOfRawData]
1104
        test    esi, esi
1105
        jnz     .copy
1106
        xor     eax, eax
1107
        rep stosb
1108
        jmp     .next
198 serge 1109
.copy:
2434 Serge 1110
        add     esi, [coff]
1111
        rep movsb
198 serge 1112
.next:
2434 Serge 1113
        pop     ecx
1114
        add     edx, sizeof.COFF_SECTION
1115
        dec     ebx
1116
        jnz     @B
1117
        pop     esi
198 serge 1118
 
1289 diamond 1119
; save some additional data from COFF file
1120
; later we will use COFF header, headers for sections and symbol table
1121
; and also relocations table for all sections
2434 Serge 1122
        mov     edx, [coff]
1123
        mov     ebx, [edx+COFF_HEADER.pSymTable]
1124
        mov     edi, dword [fileinfo+32]
1125
        sub     edi, ebx
1126
        jc      .fail_and_free_data
1127
        mov     [esi+DLLDESCR.symbols_lim], edi
1128
        add     ebx, edx
1129
        movzx   ecx, [edx+COFF_HEADER.nSections]
1130
        lea     ecx, [ecx*5]
1131
        lea     edi, [edi+ecx*8+20]
1132
        add     edx, 20
1289 diamond 1133
@@:
2434 Serge 1134
        movzx   eax, [edx+COFF_SECTION.NumReloc]
1135
        lea     eax, [eax*5]
1136
        lea     edi, [edi+eax*2]
1137
        add     edx, sizeof.COFF_SECTION
1138
        sub     ecx, 5
1139
        jnz     @b
1140
        stdcall kernel_alloc, edi
1141
        test    eax, eax
1142
        jz      .fail_and_free_data
1143
        mov     edx, [coff]
1144
        movzx   ecx, [edx+COFF_HEADER.nSections]
1145
        lea     ecx, [ecx*5]
1146
        lea     ecx, [ecx*2+5]
1147
        mov     [esi+DLLDESCR.coff_hdr], eax
1148
        push    esi
1149
        mov     esi, edx
1150
        mov     edi, eax
1151
        rep movsd
1152
        pop     esi
1153
        mov     [esi+DLLDESCR.symbols_ptr], edi
1154
        push    esi
1155
        mov     ecx, [edx+COFF_HEADER.nSymbols]
1156
        mov     [esi+DLLDESCR.symbols_num], ecx
1157
        mov     ecx, [esi+DLLDESCR.symbols_lim]
1158
        mov     esi, ebx
1159
        rep movsb
1160
        pop     esi
1161
        mov     ebx, [esi+DLLDESCR.coff_hdr]
1162
        push    esi
1163
        movzx   eax, [edx+COFF_HEADER.nSections]
1164
        lea     edx, [ebx+20]
1289 diamond 1165
@@:
2434 Serge 1166
        movzx   ecx, [edx+COFF_SECTION.NumReloc]
1167
        lea     ecx, [ecx*5]
1168
        mov     esi, [edx+COFF_SECTION.PtrReloc]
1169
        mov     [edx+COFF_SECTION.PtrReloc], edi
1170
        sub     [edx+COFF_SECTION.PtrReloc], ebx
1171
        add     esi, [coff]
1172
        shr     ecx, 1
1173
        rep movsd
1174
        adc     ecx, ecx
1175
        rep movsw
1176
        add     edx, sizeof.COFF_SECTION
1177
        dec     eax
1178
        jnz     @b
1179
        pop     esi
198 serge 1180
 
1289 diamond 1181
; fixup symbols
2434 Serge 1182
        mov     edx, ebx
1183
        mov     eax, [ebx+COFF_HEADER.nSymbols]
1184
        add     edx, 20
1185
        mov     ecx, [esi+DLLDESCR.symbols_num]
1186
        lea     ecx, [ecx*9]
1187
        add     ecx, ecx
1188
        add     ecx, [esi+DLLDESCR.symbols_ptr]
198 serge 1189
 
2434 Serge 1190
        stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
1191
                ecx, 0
1192
;          test eax, eax
1193
;          jnz @F
1289 diamond 1194
;
1195
;@@:
1196
 
2434 Serge 1197
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
1198
        test    eax, eax
1199
        jnz     @F
198 serge 1200
 
2434 Serge 1201
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
198 serge 1202
@@:
2434 Serge 1203
        mov     [esi+DLLDESCR.exports], eax
198 serge 1204
 
1289 diamond 1205
; fix relocs in the hidden copy in kernel memory to default address
1206
; it is first fix; usually this will be enough, but second fix
1207
; can be necessary if real load address will not equal assumption
2434 Serge 1208
        mov     eax, [esi+DLLDESCR.data]
1209
        sub     eax, [esi+DLLDESCR.defaultbase]
1210
        stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
198 serge 1211
 
2434 Serge 1212
        stdcall kernel_free, [coff]
916 serge 1213
 
3908 Serge 1214
        cli
1215
; initialize DLLDESCR struct
1216
        and     dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
1217
        mov     [esi+DLLDESCR.fd], dll_list
1218
        mov     eax, [dll_list.bk]
1219
        mov     [dll_list.bk], esi
1220
        mov     [esi+DLLDESCR.bk], eax
1221
        mov     [eax+DLLDESCR.fd], esi
1289 diamond 1222
.dll_already_loaded:
2434 Serge 1223
        inc     [esi+DLLDESCR.refcount]
1224
        push    esi
1225
        call    init_heap
1226
        pop     esi
1289 diamond 1227
 
2434 Serge 1228
        mov     edi, [esi+DLLDESCR.size]
1229
        stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
1230
        test    eax, eax
1231
        jnz     @f
1232
        stdcall user_alloc, edi
1233
        test    eax, eax
1234
        jz      .fail_and_dereference
917 diamond 1235
@@:
2434 Serge 1236
        mov     [img_base], eax
1237
        mov     eax, sizeof.HDLL
1238
        call    malloc
1239
        test    eax, eax
1240
        jz      .fail_and_free_user
1241
        mov     ebx, [CURRENT_TASK]
1242
        shl     ebx, 5
1243
        mov     edx, [CURRENT_TASK+ebx+TASKDATA.pid]
1244
        mov     [eax+HDLL.pid], edx
1245
        push    eax
1246
        call    init_dlls_in_thread
1247
        pop     ebx
1248
        test    eax, eax
1249
        jz      .fail_and_free_user
1250
        mov     edx, [eax+HDLL.fd]
1251
        mov     [ebx+HDLL.fd], edx
1252
        mov     [ebx+HDLL.bk], eax
1253
        mov     [eax+HDLL.fd], ebx
1254
        mov     [edx+HDLL.bk], ebx
1255
        mov     eax, ebx
1256
        mov     ebx, [img_base]
1257
        mov     [eax+HDLL.base], ebx
1258
        mov     [eax+HDLL.size], edi
1259
        mov     [eax+HDLL.refcount], 1
1260
        mov     [eax+HDLL.parent], esi
1261
        mov     edx, ebx
1262
        shr     edx, 12
1263
        or      dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
1289 diamond 1264
; copy entries of page table from kernel-side image to usermode
1265
; use copy-on-write for user-mode image, so map as readonly
2434 Serge 1266
        xor     edi, edi
1267
        mov     ecx, [esi+DLLDESCR.data]
1268
        shr     ecx, 12
1289 diamond 1269
.map_pages_loop:
2434 Serge 1270
        mov     eax, [page_tabs+ecx*4]
1271
        and     eax, not 0xFFF
1272
        or      al, PG_USER
1273
        xchg    eax, [page_tabs+edx*4]
1274
        test    al, 1
1275
        jz      @f
1276
        call    free_page
1289 diamond 1277
@@:
2434 Serge 1278
        invlpg  [ebx+edi]
1279
        inc     ecx
1280
        inc     edx
1281
        add     edi, 0x1000
1282
        cmp     edi, [esi+DLLDESCR.size]
1283
        jb      .map_pages_loop
1289 diamond 1284
 
1285
; if real user-mode base is not equal to preferred base, relocate image
2434 Serge 1286
        sub     ebx, [esi+DLLDESCR.defaultbase]
1287
        jz      @f
1288
        stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
1289 diamond 1289
@@:
1290
 
2434 Serge 1291
        mov     eax, [esi+DLLDESCR.exports]
1292
        sub     eax, [esi+DLLDESCR.defaultbase]
1293
        add     eax, [img_base]
3908 Serge 1294
        sti
2434 Serge 1295
        ret
1289 diamond 1296
.fail_and_free_data:
2434 Serge 1297
        stdcall kernel_free, [esi+DLLDESCR.data]
1289 diamond 1298
.fail_and_free_dll:
2434 Serge 1299
        mov     eax, esi
1300
        call    free
1289 diamond 1301
.fail_and_free_coff:
2434 Serge 1302
        stdcall kernel_free, [coff]
198 serge 1303
.fail:
2434 Serge 1304
        xor     eax, eax
1305
        ret
1289 diamond 1306
.fail_and_free_user:
2434 Serge 1307
        stdcall user_free, [img_base]
1289 diamond 1308
.fail_and_dereference:
2434 Serge 1309
        mov     eax, 1  ; delete 1 reference
1310
        call    dereference_dll
3908 Serge 1311
        sti
2434 Serge 1312
        xor     eax, eax
1313
        ret
198 serge 1314
endp
1315
 
1311 diamond 1316
; initialize [APPDATA.dlls_list_ptr] for given thread
1317
; DLL is per-process object, so APPDATA.dlls_list_ptr must be
1318
; kept in sync for all threads of one process.
1319
; out: eax = APPDATA.dlls_list_ptr if all is OK,
1320
; NULL if memory allocation failed
1321
init_dlls_in_thread:
2434 Serge 1322
        mov     ebx, [current_slot]
1323
        mov     eax, [ebx+APPDATA.dlls_list_ptr]
1324
        test    eax, eax
1325
        jnz     .ret
1326
        push    [ebx+APPDATA.dir_table]
1327
        mov     eax, 8
1328
        call    malloc
1329
        pop     edx
1330
        test    eax, eax
1331
        jz      .ret
1332
        mov     [eax], eax
1333
        mov     [eax+4], eax
1334
        mov     ecx, [TASK_COUNT]
1335
        mov     ebx, SLOT_BASE+256
1311 diamond 1336
.set:
2434 Serge 1337
        cmp     [ebx+APPDATA.dir_table], edx
1338
        jnz     @f
1339
        mov     [ebx+APPDATA.dlls_list_ptr], eax
1311 diamond 1340
@@:
2434 Serge 1341
        add     ebx, 256
1342
        dec     ecx
1343
        jnz     .set
1311 diamond 1344
.ret:
2434 Serge 1345
        ret
1311 diamond 1346
 
1289 diamond 1347
; in: eax = number of references to delete, esi -> DLLDESCR struc
1348
dereference_dll:
2434 Serge 1349
        sub     [esi+DLLDESCR.refcount], eax
1350
        jnz     .ret
1351
        mov     eax, [esi+DLLDESCR.fd]
1352
        mov     edx, [esi+DLLDESCR.bk]
1353
        mov     [eax+DLLDESCR.bk], edx
1354
        mov     [edx+DLLDESCR.fd], eax
1355
        stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
1356
        stdcall kernel_free, [esi+DLLDESCR.data]
1357
        mov     eax, esi
1358
        call    free
1289 diamond 1359
.ret:
2434 Serge 1360
        ret
1289 diamond 1361
 
1362
destroy_hdll:
2434 Serge 1363
        push    ebx ecx esi edi
1364
        push    eax
1365
        mov     ebx, [eax+HDLL.base]
1366
        mov     esi, [eax+HDLL.parent]
1367
        mov     edx, [esi+DLLDESCR.size]
1292 diamond 1368
; The following actions require the context of application where HDLL is mapped.
1369
; However, destroy_hdll can be called in the context of OS thread when
1370
; cleaning up objects created by the application which is destroyed.
1371
; So remember current cr3 and set it to page table of target.
2434 Serge 1372
        mov     eax, [ecx+APPDATA.dir_table]
1292 diamond 1373
; Because we cheat with cr3, disable interrupts: task switch would restore
1374
; page table from APPDATA of current thread.
1375
; Also set [current_slot] because it is used by user_free.
2434 Serge 1376
        pushf
1377
        cli
1378
        push    [current_slot]
1379
        mov     [current_slot], ecx
1380
        mov     ecx, cr3
1381
        push    ecx
1382
        mov     cr3, eax
1383
        push    ebx     ; argument for user_free
1384
        mov     eax, ebx
1385
        shr     ebx, 12
1386
        push    ebx
1387
        mov     esi, [esi+DLLDESCR.data]
1388
        shr     esi, 12
1289 diamond 1389
.unmap_loop:
2434 Serge 1390
        push    eax
1391
        mov     eax, 2
1392
        xchg    eax, [page_tabs+ebx*4]
1393
        mov     ecx, [page_tabs+esi*4]
1394
        and     eax, not 0xFFF
1395
        and     ecx, not 0xFFF
1396
        cmp     eax, ecx
1397
        jz      @f
1398
        call    free_page
1289 diamond 1399
@@:
2434 Serge 1400
        pop     eax
1401
        invlpg  [eax]
1402
        add     eax, 0x1000
1403
        inc     ebx
1404
        inc     esi
1405
        sub     edx, 0x1000
1406
        ja      .unmap_loop
1407
        pop     ebx
1408
        and     dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
1409
        call    user_free
1292 diamond 1410
; Restore context.
2434 Serge 1411
        pop     eax
1412
        mov     cr3, eax
1413
        pop     [current_slot]
1414
        popf
1292 diamond 1415
; Ok, cheating is done.
2434 Serge 1416
        pop     eax
1417
        push    eax
1418
        mov     esi, [eax+HDLL.parent]
1419
        mov     eax, [eax+HDLL.refcount]
1420
        call    dereference_dll
1421
        pop     eax
1422
        mov     edx, [eax+HDLL.bk]
1423
        mov     ebx, [eax+HDLL.fd]
1424
        mov     [ebx+HDLL.bk], edx
1425
        mov     [edx+HDLL.fd], ebx
1426
        call    free
1427
        pop     edi esi ecx ebx
1428
        ret
1289 diamond 1429
 
1311 diamond 1430
; ecx -> APPDATA for slot, esi = dlls_list_ptr
1431
destroy_all_hdlls:
2434 Serge 1432
        test    esi, esi
1433
        jz      .ret
1311 diamond 1434
.loop:
2434 Serge 1435
        mov     eax, [esi+HDLL.fd]
1436
        cmp     eax, esi
1437
        jz      free
1438
        call    destroy_hdll
1439
        jmp     .loop
1311 diamond 1440
.ret:
2434 Serge 1441
        ret
1311 diamond 1442
 
214 serge 1443
align 4
1275 serge 1444
stop_all_services:
2434 Serge 1445
        push    ebp
1446
        mov     edx, [srv.fd]
214 serge 1447
.next:
2434 Serge 1448
        cmp     edx, srv.fd-SRV.fd
1449
        je      .done
1450
        cmp     [edx+SRV.magic], ' SRV'
1451
        jne     .next
1452
        cmp     [edx+SRV.size], sizeof.SRV
1453
        jne     .next
732 serge 1454
 
2434 Serge 1455
        mov     ebx, [edx+SRV.entry]
1456
        mov     edx, [edx+SRV.fd]
1457
        test    ebx, ebx
1458
        jz      .next
732 serge 1459
 
2434 Serge 1460
        push    edx
1461
        mov     ebp, esp
1462
        push    0
1463
        push    -1
1464
        call    ebx
1465
        mov     esp, ebp
1466
        pop     edx
1467
        jmp     .next
278 serge 1468
.done:
2434 Serge 1469
        pop     ebp
1470
        ret
198 serge 1471
 
281 serge 1472
; param
291 serge 1473
;  eax= size
1474
;  ebx= pid
214 serge 1475
 
281 serge 1476
align 4
1477
create_kernel_object:
1478
 
2434 Serge 1479
        push    ebx
1480
        call    malloc
1481
        pop     ebx
1482
        test    eax, eax
1483
        jz      .fail
281 serge 1484
 
2434 Serge 1485
        mov     ecx, [current_slot]
1486
        add     ecx, APP_OBJ_OFFSET
281 serge 1487
 
2434 Serge 1488
        pushfd
1489
        cli
1490
        mov     edx, [ecx+APPOBJ.fd]
1491
        mov     [eax+APPOBJ.fd], edx
1492
        mov     [eax+APPOBJ.bk], ecx
1493
        mov     [eax+APPOBJ.pid], ebx
281 serge 1494
 
2434 Serge 1495
        mov     [ecx+APPOBJ.fd], eax
1496
        mov     [edx+APPOBJ.bk], eax
1497
        popfd
281 serge 1498
.fail:
2434 Serge 1499
        ret
281 serge 1500
 
1501
; param
1502
;  eax= object
1503
 
1504
align 4
1505
destroy_kernel_object:
1506
 
2434 Serge 1507
        pushfd
1508
        cli
1509
        mov     ebx, [eax+APPOBJ.fd]
1510
        mov     ecx, [eax+APPOBJ.bk]
1511
        mov     [ebx+APPOBJ.bk], ecx
1512
        mov     [ecx+APPOBJ.fd], ebx
1513
        popfd
281 serge 1514
 
2434 Serge 1515
        xor     edx, edx       ;clear common header
1516
        mov     [eax], edx
1517
        mov     [eax+4], edx
1518
        mov     [eax+8], edx
1519
        mov     [eax+12], edx
1520
        mov     [eax+16], edx
281 serge 1521
 
2434 Serge 1522
        call    free           ;release object memory
1523
        ret