Subversion Repositories Kolibri OS

Rev

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