forked from KolibriOS/kolibrios
[CLEVERMOUSE_PE_KERNEL] Apply CleverMouse PE patch
git-svn-id: svn://kolibrios.org@9048 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
360e379fc7
commit
eccd8f2198
@ -440,11 +440,11 @@ ends
|
||||
struct PROC
|
||||
list LHEAD
|
||||
thr_list LHEAD
|
||||
smap_list LHEAD
|
||||
heap_lock MUTEX
|
||||
heap_base rd 1
|
||||
heap_top rd 1
|
||||
mem_used rd 1
|
||||
dlls_list_ptr rd 1
|
||||
pdt_0_phys rd 1
|
||||
pdt_1_phys rd 1
|
||||
io_map_0 rd 1
|
||||
@ -651,37 +651,16 @@ struct SMEM
|
||||
name rb 32 ;+24
|
||||
ends
|
||||
|
||||
struct SMAP APPOBJ
|
||||
base dd ? ;mapped base
|
||||
parent dd ? ;SMEM
|
||||
ends
|
||||
|
||||
struct DLLDESCR
|
||||
bk dd ?
|
||||
fd dd ? ;+4
|
||||
data dd ? ;+8
|
||||
size dd ? ;+12
|
||||
timestamp dq ?
|
||||
refcount dd ?
|
||||
defaultbase dd ?
|
||||
coff_hdr dd ?
|
||||
symbols_ptr dd ?
|
||||
symbols_num dd ?
|
||||
symbols_lim dd ?
|
||||
exports dd ? ;export table
|
||||
name rb 260
|
||||
ends
|
||||
|
||||
struct HDLL
|
||||
fd dd ? ;next object in list
|
||||
bk dd ? ;prev object in list
|
||||
pid dd ? ;owner id
|
||||
|
||||
struct SMAP
|
||||
fd dd ? ;next in mmapped list
|
||||
bk dd ? ;prev in mmapped list
|
||||
base dd ? ;mapped base
|
||||
size dd ? ;mapped size
|
||||
refcount dd ? ;reference counter for this process and this lib
|
||||
parent dd ? ;DLLDESCR
|
||||
type dd ? ;SMAP_TYPE_SMEM or SMAP_TYPE_PE
|
||||
parent dd ? ;SMEM or PEDESCR
|
||||
ends
|
||||
SMAP_TYPE_SMEM = 1
|
||||
SMAP_TYPE_PE = 2
|
||||
|
||||
struct DQ
|
||||
lo dd ?
|
||||
@ -810,6 +789,55 @@ struct PCIDEV
|
||||
owner dd ? ; pointer to SRV or 0
|
||||
ends
|
||||
|
||||
struct PEDESCR
|
||||
bk dd ?
|
||||
fd dd ?
|
||||
size dd ? ; in pages
|
||||
timestamp dq ?
|
||||
refcount dd ?
|
||||
defaultbase dd ?
|
||||
name dd ?
|
||||
entry dd ?
|
||||
stacksize dd ?
|
||||
page_array_lock MUTEX
|
||||
; After those fields the array follows, one dword per every of [size] pages.
|
||||
; The value of every field has 3 parts:
|
||||
; - upper 20 bits are page number or zero;
|
||||
; - next 4 bits are access rights shareable/executable/readable/writable
|
||||
; in the same order as IMAGE_SCN_MEM_xxx shifted appropriately;
|
||||
; - lower 8 bits are reference counter.
|
||||
; The exact meaning depends on page type.
|
||||
; * For a page with data in non-shareable section
|
||||
; which has at least one unmodified copy:
|
||||
; - upper 20 bits are page number for unmodified copy,
|
||||
; - reference counter = number of unmodified copies is nonzero up to 0xFF.
|
||||
; If reference counter reaches 0xFF, it becomes locked at this value.
|
||||
; If reference counter reaches zero, the last copy changes ownership
|
||||
; to the last process,
|
||||
; and the page is converted to the following state.
|
||||
; * For a page with data in non-shareable section
|
||||
; with no unmodified copies:
|
||||
; - all fields are reset to zero.
|
||||
; The original content is lost; map_pe_usermode would reload from file.
|
||||
; * For a page with zeroes in non-shareable section:
|
||||
; - upper 20 bits are zero,
|
||||
; - lower 8 bits are 0xFF.
|
||||
; * For a page in shareable section with data or with zeroes:
|
||||
; - upper 20 bits are page number for all copies,
|
||||
; - lower 8 bits are reference counter from 1 to 0xFF.
|
||||
; Reference counter does not actually matter here,
|
||||
; it equals [refcount] unless 0xFF was once reached,
|
||||
; but is kept for consistency.
|
||||
ends
|
||||
|
||||
struct SHARED_LOCKED_PAGE
|
||||
fd dd ?
|
||||
bk dd ?
|
||||
address dd ?
|
||||
parent dd ?
|
||||
offs dd ?
|
||||
ends
|
||||
|
||||
struct IDE_DATA
|
||||
ProgrammingInterface dd ?
|
||||
Interrupt dw ?
|
||||
@ -933,6 +961,19 @@ struct COFF_SECTION
|
||||
NumLinenum dw ?
|
||||
Characteristics dd ?
|
||||
ends
|
||||
IMAGE_SCN_MEM_SHARED = 10000000h
|
||||
IMAGE_SCN_MEM_EXECUTE = 20000000h
|
||||
IMAGE_SCN_MEM_READ = 40000000h
|
||||
IMAGE_SCN_MEM_WRITE = 80000000h
|
||||
|
||||
struct STRIPPED_PE_SECTION
|
||||
Name rb 8
|
||||
VirtualSize dd ?
|
||||
VirtualAddress dd ?
|
||||
SizeOfRawData dd ?
|
||||
PtrRawData dd ?
|
||||
Characteristics dd ?
|
||||
ends
|
||||
|
||||
struct COFF_RELOC
|
||||
VirtualAddress dd ?
|
||||
@ -971,6 +1012,62 @@ SPE_DIRECTORY_IMPORT = 0
|
||||
SPE_DIRECTORY_EXPORT = 1
|
||||
SPE_DIRECTORY_BASERELOC = 2
|
||||
|
||||
struct IMAGE_DATA_DIRECTORY
|
||||
VirtualAddress dd ?
|
||||
isize dd ?
|
||||
ends
|
||||
|
||||
struct IMAGE_OPTIONAL_HEADER32
|
||||
Magic dw ?
|
||||
MajorLinkerVersion db ?
|
||||
MinorLinkerVersion db ?
|
||||
SizeOfCode dd ?
|
||||
SizeOfInitializedData dd ?
|
||||
SizeOfUninitializedData dd ?
|
||||
AddressOfEntryPoint dd ?
|
||||
BaseOfCode dd ?
|
||||
BaseOfData dd ?
|
||||
ImageBase dd ?
|
||||
SectionAlignment dd ?
|
||||
FileAlignment dd ?
|
||||
MajorOperatingSystemVersion dw ?
|
||||
MinorOperatingSystemVersion dw ?
|
||||
MajorImageVersion dw ?
|
||||
MinorImageVersion dw ?
|
||||
MajorSubsystemVersion dw ?
|
||||
MinorSubsystemVersion dw ?
|
||||
Win32VersionValue dd ?
|
||||
SizeOfImage dd ?
|
||||
SizeOfHeaders dd ?
|
||||
CheckSum dd ?
|
||||
Subsystem dw ?
|
||||
DllCharacteristics dw ?
|
||||
SizeOfStackReserve dd ?
|
||||
SizeOfStackCommit dd ?
|
||||
SizeOfHeapReserve dd ?
|
||||
SizeOfHeapCommit dd ?
|
||||
LoaderFlags dd ?
|
||||
NumberOfDirectories dd ?
|
||||
DataDirectory IMAGE_DATA_DIRECTORY ?
|
||||
Directories rb sizeof.IMAGE_DATA_DIRECTORY*15
|
||||
ends
|
||||
|
||||
struct IMAGE_FILE_HEADER
|
||||
Machine dw ?
|
||||
NumberOfSections dw ?
|
||||
TimeDateStamp dd ?
|
||||
PointerToSymbolTable dd ?
|
||||
NumberOfSymbols dd ?
|
||||
SizeOfOptionalHeader dw ?
|
||||
Characteristics dw ?
|
||||
ends
|
||||
|
||||
struct IMAGE_NT_HEADERS
|
||||
Signature dd ?
|
||||
FileHeader IMAGE_FILE_HEADER
|
||||
OptionalHeader IMAGE_OPTIONAL_HEADER32
|
||||
ends
|
||||
|
||||
struct IOCTL
|
||||
handle dd ?
|
||||
io_code dd ?
|
||||
|
@ -901,9 +901,13 @@ align 4
|
||||
proc load_library stdcall, file_name:dword, encoding:dword
|
||||
locals
|
||||
fullname dd ?
|
||||
fileinfo rb 40
|
||||
filesize dd ?
|
||||
coff dd ?
|
||||
img_base dd ?
|
||||
img_size dd ?
|
||||
symbols_ptr dd ?
|
||||
symbols_lim dd ?
|
||||
exports dd ?
|
||||
endl
|
||||
|
||||
; resolve file name
|
||||
@ -917,105 +921,19 @@ proc load_library stdcall, file_name:dword, encoding:dword
|
||||
pop ebp
|
||||
test eax, eax
|
||||
jz .fail
|
||||
; scan for required DLL in list of already loaded for this process,
|
||||
; ignore timestamp
|
||||
cli
|
||||
mov esi, [current_process]
|
||||
mov edi, [fullname]
|
||||
mov ebx, [esi+PROC.dlls_list_ptr]
|
||||
test ebx, ebx
|
||||
jz .not_in_process
|
||||
mov esi, [ebx+HDLL.fd]
|
||||
.scan_in_process:
|
||||
cmp esi, ebx
|
||||
jz .not_in_process
|
||||
mov eax, [esi+HDLL.parent]
|
||||
add eax, DLLDESCR.name
|
||||
stdcall strncmp, eax, edi, -1
|
||||
test eax, eax
|
||||
jnz .next_in_process
|
||||
; simple variant: load DLL which is already loaded in this process
|
||||
; just increment reference counters and return address of exports table
|
||||
inc [esi+HDLL.refcount]
|
||||
mov ecx, [esi+HDLL.parent]
|
||||
inc [ecx+DLLDESCR.refcount]
|
||||
mov eax, [ecx+DLLDESCR.exports]
|
||||
sub eax, [ecx+DLLDESCR.defaultbase]
|
||||
add eax, [esi+HDLL.base]
|
||||
sti
|
||||
push eax
|
||||
stdcall kernel_free, [fullname]
|
||||
pop eax
|
||||
ret
|
||||
|
||||
.next_in_process:
|
||||
mov esi, [esi+HDLL.fd]
|
||||
jmp .scan_in_process
|
||||
|
||||
.not_in_process:
|
||||
; scan in full list, compare timestamp
|
||||
sti
|
||||
lea eax, [fileinfo]
|
||||
stdcall get_fileinfo, edi, eax
|
||||
test eax, eax
|
||||
jnz .fail
|
||||
cli
|
||||
mov esi, [dll_list.fd]
|
||||
.scan_for_dlls:
|
||||
cmp esi, dll_list
|
||||
jz .load_new
|
||||
lea eax, [esi+DLLDESCR.name]
|
||||
stdcall strncmp, eax, edi, -1
|
||||
test eax, eax
|
||||
jnz .continue_scan
|
||||
.test_prev_dll:
|
||||
mov eax, dword [fileinfo+24]; last modified time
|
||||
mov edx, dword [fileinfo+28]; last modified date
|
||||
cmp dword [esi+DLLDESCR.timestamp], eax
|
||||
jnz .continue_scan
|
||||
cmp dword [esi+DLLDESCR.timestamp+4], edx
|
||||
jz .dll_already_loaded
|
||||
.continue_scan:
|
||||
mov esi, [esi+DLLDESCR.fd]
|
||||
jmp .scan_for_dlls
|
||||
|
||||
; new DLL
|
||||
.load_new:
|
||||
sti
|
||||
; load file
|
||||
stdcall load_file, edi
|
||||
stdcall load_file, [fullname]
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov [coff], eax
|
||||
mov dword [fileinfo+32], ebx
|
||||
|
||||
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
|
||||
mov esi, edi
|
||||
mov ecx, -1
|
||||
xor eax, eax
|
||||
repnz scasb
|
||||
not ecx
|
||||
lea eax, [ecx+sizeof.DLLDESCR]
|
||||
push ecx
|
||||
call malloc
|
||||
pop ecx
|
||||
test eax, eax
|
||||
jz .fail_and_free_coff
|
||||
; save timestamp
|
||||
lea edi, [eax+DLLDESCR.name]
|
||||
rep movsb
|
||||
mov esi, eax
|
||||
mov eax, dword [fileinfo+24]
|
||||
mov dword [esi+DLLDESCR.timestamp], eax
|
||||
mov eax, dword [fileinfo+28]
|
||||
mov dword [esi+DLLDESCR.timestamp+4], eax
|
||||
mov [filesize], ebx
|
||||
|
||||
; calculate size of loaded DLL
|
||||
mov edx, [coff]
|
||||
movzx ecx, [edx+COFF_HEADER.nSections]
|
||||
movzx ecx, [eax+COFF_HEADER.nSections]
|
||||
xor ebx, ebx
|
||||
|
||||
add edx, 20
|
||||
lea edx, [eax+20]
|
||||
@@:
|
||||
call coff_get_align
|
||||
add ebx, eax
|
||||
@ -1026,31 +944,19 @@ proc load_library stdcall, file_name:dword, encoding:dword
|
||||
dec ecx
|
||||
jnz @B
|
||||
; it must be nonzero and not too big
|
||||
mov [esi+DLLDESCR.size], ebx
|
||||
mov [img_size], ebx
|
||||
test ebx, ebx
|
||||
jz .fail_and_free_dll
|
||||
cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
|
||||
ja .fail_and_free_dll
|
||||
; allocate memory for kernel-side image
|
||||
stdcall kernel_alloc, ebx
|
||||
jz .fail_and_free_coff
|
||||
cmp ebx, 0x10000000
|
||||
ja .fail_and_free_coff
|
||||
; allocate memory
|
||||
call init_heap
|
||||
stdcall user_alloc, [img_size]
|
||||
test eax, eax
|
||||
jz .fail_and_free_dll
|
||||
mov [esi+DLLDESCR.data], eax
|
||||
; calculate preferred base address
|
||||
add ebx, 0x1FFF
|
||||
and ebx, not 0xFFF
|
||||
mov ecx, [dll_cur_addr]
|
||||
lea edx, [ecx+ebx]
|
||||
cmp edx, MAX_DEFAULT_DLL_ADDR
|
||||
jb @f
|
||||
mov ecx, MIN_DEFAULT_DLL_ADDR
|
||||
lea edx, [ecx+ebx]
|
||||
@@:
|
||||
mov [esi+DLLDESCR.defaultbase], ecx
|
||||
mov [dll_cur_addr], edx
|
||||
jz .fail_and_free_coff
|
||||
mov [img_base], eax
|
||||
|
||||
; copy sections and set correct values for VirtualAddress'es in headers
|
||||
push esi
|
||||
mov edx, [coff]
|
||||
movzx ebx, [edx+COFF_HEADER.nSections]
|
||||
mov edi, eax
|
||||
@ -1058,15 +964,11 @@ proc load_library stdcall, file_name:dword, encoding:dword
|
||||
cld
|
||||
@@:
|
||||
call coff_get_align
|
||||
add ecx, eax
|
||||
add edi, eax
|
||||
not eax
|
||||
and ecx, eax
|
||||
and edi, eax
|
||||
mov [edx+COFF_SECTION.VirtualAddress], ecx
|
||||
add ecx, [edx+COFF_SECTION.SizeOfRawData]
|
||||
mov [edx+COFF_SECTION.VirtualAddress], edi
|
||||
mov esi, [edx+COFF_SECTION.PtrRawData]
|
||||
push ecx
|
||||
mov ecx, [edx+COFF_SECTION.SizeOfRawData]
|
||||
test esi, esi
|
||||
jnz .copy
|
||||
@ -1077,282 +979,78 @@ proc load_library stdcall, file_name:dword, encoding:dword
|
||||
add esi, [coff]
|
||||
rep movsb
|
||||
.next:
|
||||
pop ecx
|
||||
add edx, sizeof.COFF_SECTION
|
||||
dec ebx
|
||||
jnz @B
|
||||
pop esi
|
||||
|
||||
; save some additional data from COFF file
|
||||
; later we will use COFF header, headers for sections and symbol table
|
||||
; and also relocations table for all sections
|
||||
mov edx, [coff]
|
||||
mov ebx, [edx+COFF_HEADER.pSymTable]
|
||||
mov edi, dword [fileinfo+32]
|
||||
mov edi, [filesize]
|
||||
sub edi, ebx
|
||||
jc .fail_and_free_data
|
||||
mov [esi+DLLDESCR.symbols_lim], edi
|
||||
mov [symbols_lim], edi
|
||||
add ebx, edx
|
||||
movzx ecx, [edx+COFF_HEADER.nSections]
|
||||
lea ecx, [ecx*5]
|
||||
lea edi, [edi+ecx*8+20]
|
||||
add edx, 20
|
||||
@@:
|
||||
movzx eax, [edx+COFF_SECTION.NumReloc]
|
||||
lea eax, [eax*5]
|
||||
lea edi, [edi+eax*2]
|
||||
add edx, sizeof.COFF_SECTION
|
||||
sub ecx, 5
|
||||
jnz @b
|
||||
stdcall kernel_alloc, edi
|
||||
test eax, eax
|
||||
jz .fail_and_free_data
|
||||
mov edx, [coff]
|
||||
movzx ecx, [edx+COFF_HEADER.nSections]
|
||||
lea ecx, [ecx*5]
|
||||
lea ecx, [ecx*2+5]
|
||||
mov [esi+DLLDESCR.coff_hdr], eax
|
||||
push esi
|
||||
mov esi, edx
|
||||
mov edi, eax
|
||||
rep movsd
|
||||
pop esi
|
||||
mov [esi+DLLDESCR.symbols_ptr], edi
|
||||
push esi
|
||||
mov ecx, [edx+COFF_HEADER.nSymbols]
|
||||
mov [esi+DLLDESCR.symbols_num], ecx
|
||||
mov ecx, [esi+DLLDESCR.symbols_lim]
|
||||
mov esi, ebx
|
||||
rep movsb
|
||||
pop esi
|
||||
mov ebx, [esi+DLLDESCR.coff_hdr]
|
||||
push esi
|
||||
movzx eax, [edx+COFF_HEADER.nSections]
|
||||
lea edx, [ebx+20]
|
||||
@@:
|
||||
movzx ecx, [edx+COFF_SECTION.NumReloc]
|
||||
lea ecx, [ecx*5]
|
||||
mov esi, [edx+COFF_SECTION.PtrReloc]
|
||||
mov [edx+COFF_SECTION.PtrReloc], edi
|
||||
sub [edx+COFF_SECTION.PtrReloc], ebx
|
||||
add esi, [coff]
|
||||
shr ecx, 1
|
||||
rep movsd
|
||||
adc ecx, ecx
|
||||
rep movsw
|
||||
add edx, sizeof.COFF_SECTION
|
||||
dec eax
|
||||
jnz @b
|
||||
pop esi
|
||||
; coff_hdr = coff
|
||||
; symbols_num = coff.nSymbols
|
||||
mov [symbols_ptr], ebx
|
||||
mov ebx, edx
|
||||
|
||||
; fixup symbols
|
||||
mov edx, ebx
|
||||
mov eax, [ebx+COFF_HEADER.nSymbols]
|
||||
mov eax, [edx+COFF_HEADER.nSymbols]
|
||||
add edx, 20
|
||||
mov ecx, [esi+DLLDESCR.symbols_num]
|
||||
lea ecx, [ecx*9]
|
||||
lea ecx, [eax*9]
|
||||
add ecx, ecx
|
||||
add ecx, [esi+DLLDESCR.symbols_ptr]
|
||||
add ecx, [symbols_ptr]
|
||||
|
||||
stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
|
||||
stdcall fix_coff_symbols, edx, [symbols_ptr], eax, \
|
||||
ecx, 0
|
||||
; test eax, eax
|
||||
; jnz @F
|
||||
;
|
||||
;@@:
|
||||
|
||||
stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
|
||||
stdcall get_coff_sym, [symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
|
||||
test eax, eax
|
||||
jnz @F
|
||||
|
||||
stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
|
||||
stdcall get_coff_sym, [symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
|
||||
@@:
|
||||
mov [esi+DLLDESCR.exports], eax
|
||||
mov [exports], eax
|
||||
|
||||
; fix relocs in the hidden copy in kernel memory to default address
|
||||
; it is first fix; usually this will be enough, but second fix
|
||||
; can be necessary if real load address will not equal assumption
|
||||
mov eax, [esi+DLLDESCR.data]
|
||||
sub eax, [esi+DLLDESCR.defaultbase]
|
||||
stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
|
||||
stdcall fix_coff_relocs, ebx, [symbols_ptr], 0
|
||||
|
||||
stdcall kernel_free, [coff]
|
||||
|
||||
cli
|
||||
; initialize DLLDESCR struct
|
||||
and dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
|
||||
mov [esi+DLLDESCR.fd], dll_list
|
||||
mov eax, [dll_list.bk]
|
||||
mov [dll_list.bk], esi
|
||||
mov [esi+DLLDESCR.bk], eax
|
||||
mov [eax+DLLDESCR.fd], esi
|
||||
.dll_already_loaded:
|
||||
stdcall kernel_free, [fullname]
|
||||
inc [esi+DLLDESCR.refcount]
|
||||
push esi
|
||||
call init_heap
|
||||
pop esi
|
||||
mov edi, [esi+DLLDESCR.size]
|
||||
stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
|
||||
test eax, eax
|
||||
jnz @f
|
||||
stdcall user_alloc, edi
|
||||
test eax, eax
|
||||
jz .fail_and_dereference
|
||||
@@:
|
||||
mov [img_base], eax
|
||||
mov eax, sizeof.HDLL
|
||||
call malloc
|
||||
test eax, eax
|
||||
jz .fail_and_free_user
|
||||
mov ebx, [current_slot_idx]
|
||||
shl ebx, 5
|
||||
mov edx, [TASK_TABLE+ebx+TASKDATA.pid]
|
||||
mov [eax+HDLL.pid], edx
|
||||
push eax
|
||||
call init_dlls_in_thread
|
||||
pop ebx
|
||||
test eax, eax
|
||||
jz .fail_and_free_user
|
||||
mov edx, [eax+HDLL.fd]
|
||||
mov [ebx+HDLL.fd], edx
|
||||
mov [ebx+HDLL.bk], eax
|
||||
mov [eax+HDLL.fd], ebx
|
||||
mov [edx+HDLL.bk], ebx
|
||||
mov eax, ebx
|
||||
mov ebx, [img_base]
|
||||
mov [eax+HDLL.base], ebx
|
||||
mov [eax+HDLL.size], edi
|
||||
mov [eax+HDLL.refcount], 1
|
||||
mov [eax+HDLL.parent], esi
|
||||
mov edx, ebx
|
||||
shr edx, 12
|
||||
or dword [page_tabs+(edx-1)*4], MEM_BLOCK_DONT_FREE
|
||||
; copy entries of page table from kernel-side image to usermode
|
||||
; use copy-on-write for user-mode image, so map as readonly
|
||||
xor edi, edi
|
||||
mov ecx, [esi+DLLDESCR.data]
|
||||
shr ecx, 12
|
||||
.map_pages_loop:
|
||||
mov eax, [page_tabs+ecx*4]
|
||||
and eax, not 0xFFF
|
||||
or al, PG_UR
|
||||
xchg eax, [page_tabs+edx*4]
|
||||
test al, 1
|
||||
jz @f
|
||||
call free_page
|
||||
@@:
|
||||
invlpg [ebx+edi]
|
||||
inc ecx
|
||||
inc edx
|
||||
add edi, 0x1000
|
||||
cmp edi, [esi+DLLDESCR.size]
|
||||
jb .map_pages_loop
|
||||
|
||||
; if real user-mode base is not equal to preferred base, relocate image
|
||||
sub ebx, [esi+DLLDESCR.defaultbase]
|
||||
jz @f
|
||||
stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
|
||||
@@:
|
||||
|
||||
mov eax, [esi+DLLDESCR.exports]
|
||||
sub eax, [esi+DLLDESCR.defaultbase]
|
||||
add eax, [img_base]
|
||||
sti
|
||||
mov eax, [exports]
|
||||
ret
|
||||
|
||||
.fail_and_free_data:
|
||||
stdcall kernel_free, [esi+DLLDESCR.data]
|
||||
.fail_and_free_dll:
|
||||
mov eax, esi
|
||||
call free
|
||||
stdcall user_free, [img_base]
|
||||
.fail_and_free_coff:
|
||||
stdcall kernel_free, [coff]
|
||||
.fail:
|
||||
stdcall kernel_free, [fullname]
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.fail_and_free_user:
|
||||
stdcall user_free, [img_base]
|
||||
.fail_and_dereference:
|
||||
mov eax, 1 ; delete 1 reference
|
||||
call dereference_dll
|
||||
sti
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; initialize [APPDATA.dlls_list_ptr] for given thread
|
||||
; DLL is per-process object, so APPDATA.dlls_list_ptr must be
|
||||
; kept in sync for all threads of one process.
|
||||
; out: eax = APPDATA.dlls_list_ptr if all is OK,
|
||||
; NULL if memory allocation failed
|
||||
init_dlls_in_thread:
|
||||
mov ebx, [current_process]
|
||||
mov eax, [ebx+PROC.dlls_list_ptr]
|
||||
test eax, eax
|
||||
jnz .ret
|
||||
|
||||
mov eax, 8
|
||||
call malloc ; FIXME
|
||||
test eax, eax
|
||||
jz .ret
|
||||
|
||||
mov [eax], eax
|
||||
mov [eax+4], eax
|
||||
|
||||
mov ebx, [current_process]
|
||||
mov [ebx+PROC.dlls_list_ptr], eax
|
||||
.ret:
|
||||
ret
|
||||
|
||||
; in: eax = number of references to delete, esi -> DLLDESCR struc
|
||||
dereference_dll:
|
||||
sub [esi+DLLDESCR.refcount], eax
|
||||
jnz .ret
|
||||
mov eax, [esi+DLLDESCR.fd]
|
||||
mov edx, [esi+DLLDESCR.bk]
|
||||
mov [eax+DLLDESCR.bk], edx
|
||||
mov [edx+DLLDESCR.fd], eax
|
||||
stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
|
||||
stdcall kernel_free, [esi+DLLDESCR.data]
|
||||
; in: esi -> PEDESCR struct
|
||||
proc dereference_pe
|
||||
mov ecx, pe_list_mutex
|
||||
call mutex_lock
|
||||
dec [esi+PEDESCR.refcount]
|
||||
jnz mutex_unlock
|
||||
mov eax, [esi+PEDESCR.fd]
|
||||
mov edx, [esi+PEDESCR.bk]
|
||||
mov [eax+PEDESCR.bk], edx
|
||||
mov [edx+PEDESCR.fd], eax
|
||||
call mutex_unlock
|
||||
mov eax, esi
|
||||
call free
|
||||
.ret:
|
||||
ret
|
||||
|
||||
destroy_hdll:
|
||||
push ebx ecx esi edi
|
||||
mov ebx, [eax+HDLL.base]
|
||||
mov esi, [eax+HDLL.parent]
|
||||
mov edx, [esi+DLLDESCR.size]
|
||||
|
||||
push eax
|
||||
mov esi, [eax+HDLL.parent]
|
||||
mov eax, [eax+HDLL.refcount]
|
||||
call dereference_dll
|
||||
pop eax
|
||||
mov edx, [eax+HDLL.bk]
|
||||
mov ebx, [eax+HDLL.fd]
|
||||
mov [ebx+HDLL.bk], edx
|
||||
mov [edx+HDLL.fd], ebx
|
||||
call free
|
||||
pop edi esi ecx ebx
|
||||
ret
|
||||
|
||||
; ecx -> APPDATA for slot, esi = dlls_list_ptr
|
||||
destroy_all_hdlls:
|
||||
test esi, esi
|
||||
jz .ret
|
||||
.loop:
|
||||
mov eax, [esi+HDLL.fd]
|
||||
cmp eax, esi
|
||||
jz free
|
||||
call destroy_hdll
|
||||
jmp .loop
|
||||
.ret:
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
stop_all_services:
|
||||
|
@ -23,8 +23,13 @@ MEM_BLOCK_FREE = 0x04
|
||||
MEM_BLOCK_USED = 0x08
|
||||
MEM_BLOCK_DONT_FREE = 0x10
|
||||
|
||||
LAZY_ALLOC_PAGE = 2
|
||||
LAZY_ALLOC_UNREADABLE = 20h
|
||||
LAZY_ALLOC_UNWRITABLE = 40h
|
||||
|
||||
macro calc_index op
|
||||
{ shr op, 12
|
||||
{
|
||||
shr op, 12
|
||||
dec op
|
||||
cmp op, 63
|
||||
jna @f
|
||||
@ -561,35 +566,42 @@ proc init_heap
|
||||
sub eax, PAGE_SIZE
|
||||
ret
|
||||
@@:
|
||||
lea ecx, [ebx + PROC.heap_lock]
|
||||
call mutex_init
|
||||
|
||||
mov esi, [ebx + PROC.mem_used]
|
||||
add esi, 4095
|
||||
and esi, not 4095
|
||||
mov [ebx + PROC.mem_used], esi
|
||||
mov edx, [ebx+PROC.mem_used]
|
||||
add edx, 4095
|
||||
and edx, not 4095
|
||||
mov [ebx+PROC.mem_used], edx
|
||||
mov eax, HEAP_TOP
|
||||
mov [ebx + PROC.heap_base], esi
|
||||
mov [ebx + PROC.heap_top], eax
|
||||
mov [ebx+PROC.heap_base], edx
|
||||
mov [ebx+PROC.heap_top], eax
|
||||
|
||||
sub eax, esi
|
||||
shr esi, 10
|
||||
sub eax, edx
|
||||
shr edx, 10
|
||||
mov ecx, eax
|
||||
sub eax, PAGE_SIZE
|
||||
or ecx, MEM_BLOCK_FREE
|
||||
mov [page_tabs + esi], ecx
|
||||
mov [page_tabs + edx], ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc user_alloc stdcall, alloc_size:dword
|
||||
proc user_alloc ;stdcall, alloc_size:dword
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_lock
|
||||
stdcall user_alloc_nolock, [esp+4]
|
||||
push eax
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
pop eax
|
||||
ret 4
|
||||
endp
|
||||
|
||||
proc user_alloc_nolock stdcall, alloc_size:dword
|
||||
push ebx esi edi
|
||||
|
||||
mov ebx, [current_process]
|
||||
lea ecx, [ebx + PROC.heap_lock]
|
||||
call mutex_lock
|
||||
|
||||
mov ecx, [alloc_size]
|
||||
add ecx, (4095 + PAGE_SIZE)
|
||||
and ecx, not 4095
|
||||
@ -628,15 +640,6 @@ proc user_alloc stdcall, alloc_size:dword
|
||||
jnz @B
|
||||
.no:
|
||||
|
||||
mov edx, [current_process]
|
||||
mov ebx, [alloc_size]
|
||||
add ebx, 0xFFF
|
||||
and ebx, not 0xFFF
|
||||
add [edx + PROC.mem_used], ebx
|
||||
|
||||
lea ecx, [edx + PROC.heap_lock]
|
||||
call mutex_unlock
|
||||
|
||||
lea eax, [esi + 4096]
|
||||
|
||||
pop edi
|
||||
@ -652,9 +655,6 @@ proc user_alloc stdcall, alloc_size:dword
|
||||
add esi, eax
|
||||
jmp .scan
|
||||
.m_exit:
|
||||
mov ecx, [current_process]
|
||||
lea ecx, [ecx + PROC.heap_lock]
|
||||
call mutex_unlock
|
||||
|
||||
xor eax, eax
|
||||
pop edi
|
||||
@ -664,15 +664,25 @@ proc user_alloc stdcall, alloc_size:dword
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc user_alloc_at stdcall, address:dword, alloc_size:dword
|
||||
proc user_alloc_at ;stdcall, address:dword, alloc_size:dword
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_lock
|
||||
stdcall user_alloc_at_nolock, [esp+8], [esp+8]
|
||||
push eax
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
pop eax
|
||||
ret 8
|
||||
endp
|
||||
|
||||
proc user_alloc_at_nolock stdcall, address:dword, alloc_size:dword
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov ebx, [current_process]
|
||||
lea ecx, [ebx + PROC.heap_lock]
|
||||
call mutex_lock
|
||||
|
||||
mov edx, [address]
|
||||
and edx, not 0xFFF
|
||||
@ -697,9 +707,6 @@ proc user_alloc_at stdcall, address:dword, alloc_size:dword
|
||||
mov esi, ecx
|
||||
jmp .scan
|
||||
.error:
|
||||
mov ecx, [current_process]
|
||||
lea ecx, [ecx + PROC.heap_lock]
|
||||
call mutex_unlock
|
||||
|
||||
xor eax, eax
|
||||
pop edi
|
||||
@ -751,16 +758,7 @@ proc user_alloc_at stdcall, address:dword, alloc_size:dword
|
||||
or cl, MEM_BLOCK_FREE
|
||||
mov [page_tabs + ebx*4], ecx
|
||||
|
||||
.nothird:
|
||||
mov edx, [current_process]
|
||||
mov ebx, [alloc_size]
|
||||
add ebx, 0xFFF
|
||||
and ebx, not 0xFFF
|
||||
add [edx + PROC.mem_used], ebx
|
||||
|
||||
lea ecx, [edx + PROC.heap_lock]
|
||||
call mutex_unlock
|
||||
|
||||
.nothird:
|
||||
mov eax, [address]
|
||||
|
||||
pop edi
|
||||
@ -775,8 +773,6 @@ proc user_free stdcall, base:dword
|
||||
push esi
|
||||
|
||||
mov esi, [base]
|
||||
test esi, esi
|
||||
jz .fail
|
||||
|
||||
push ebx
|
||||
|
||||
@ -786,12 +782,18 @@ proc user_free stdcall, base:dword
|
||||
|
||||
xor ebx, ebx
|
||||
shr esi, 12
|
||||
jz .cantfree
|
||||
mov eax, [page_tabs + (esi-1)*4]
|
||||
test al, MEM_BLOCK_USED
|
||||
jz .cantfree
|
||||
test al, MEM_BLOCK_DONT_FREE
|
||||
jnz .cantfree
|
||||
|
||||
push 0
|
||||
virtual at esp
|
||||
.num_released_pages dd ?
|
||||
end virtual
|
||||
|
||||
and eax, not 4095
|
||||
mov ecx, eax
|
||||
or al, MEM_BLOCK_FREE
|
||||
@ -800,35 +802,33 @@ proc user_free stdcall, base:dword
|
||||
mov ebx, ecx
|
||||
shr ecx, 12
|
||||
jz .released
|
||||
.release:
|
||||
xor eax, eax
|
||||
xchg eax, [page_tabs + esi*4]
|
||||
test al, 1
|
||||
jz @F
|
||||
test eax, PG_SHARED
|
||||
jnz @F
|
||||
call free_page
|
||||
.release:
|
||||
mov edx, [page_tabs+esi*4]
|
||||
mov dword [page_tabs+esi*4], 0
|
||||
mov eax, esi
|
||||
shl eax, 12
|
||||
invlpg [eax]
|
||||
@@:
|
||||
test dl, 1
|
||||
jz @F
|
||||
inc [.num_released_pages]
|
||||
test edx, PG_SHARED
|
||||
jnz @f
|
||||
mov eax, edx
|
||||
call free_page
|
||||
@@:
|
||||
inc esi
|
||||
dec ecx
|
||||
jnz .release
|
||||
|
||||
.released:
|
||||
push edi
|
||||
.released:
|
||||
|
||||
pop eax ; .num_released_pages
|
||||
shl eax, 12
|
||||
mov edx, [current_process]
|
||||
lea ecx, [edx + PROC.heap_lock]
|
||||
mov esi, dword [edx + PROC.heap_base]
|
||||
mov edi, dword [edx + PROC.heap_top]
|
||||
sub ebx, [edx + PROC.mem_used]
|
||||
neg ebx
|
||||
mov [edx + PROC.mem_used], ebx
|
||||
sub [edx + PROC.mem_used], eax
|
||||
call user_normalize
|
||||
pop edi
|
||||
.exit:
|
||||
.exit:
|
||||
call mutex_unlock
|
||||
|
||||
xor eax, eax
|
||||
@ -850,18 +850,21 @@ endp
|
||||
|
||||
align 4
|
||||
proc user_unmap stdcall, base:dword, offset:dword, size:dword
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_lock
|
||||
|
||||
push ebx
|
||||
|
||||
mov ebx, [base] ; must be valid pointer
|
||||
test ebx, ebx
|
||||
jz .error
|
||||
|
||||
mov edx, [offset] ; check offset
|
||||
add edx, ebx ; must be below 2Gb app limit
|
||||
jc .error
|
||||
js .error
|
||||
|
||||
shr ebx, 12 ; chek block attributes
|
||||
jz .error
|
||||
lea ebx, [page_tabs + ebx*4]
|
||||
mov eax, [ebx-4] ; block attributes
|
||||
test al, MEM_BLOCK_USED
|
||||
@ -887,36 +890,63 @@ proc user_unmap stdcall, base:dword, offset:dword, size:dword
|
||||
and ebx, not 4095 ; is it required ?
|
||||
add ebx, [base]
|
||||
|
||||
.unmap:
|
||||
push 0
|
||||
virtual at esp
|
||||
.num_released_pages dd ?
|
||||
end virtual
|
||||
|
||||
.unmap:
|
||||
mov eax, [edx] ; get page addres
|
||||
test al, 1 ; page mapped ?
|
||||
jz @F
|
||||
jz .next
|
||||
test eax, PG_SHARED ; page shared ?
|
||||
jnz @F
|
||||
mov dword[edx], MEM_BLOCK_RESERVED
|
||||
jnz .next
|
||||
inc [.num_released_pages]
|
||||
mov dword [edx], LAZY_ALLOC_PAGE
|
||||
; mark page as reserved
|
||||
test eax, PG_READ
|
||||
jnz @f
|
||||
or dword [edx], LAZY_ALLOC_UNREADABLE
|
||||
@@:
|
||||
test eax, PG_WRITE
|
||||
jnz @f
|
||||
or dword [edx], LAZY_ALLOC_UNWRITABLE
|
||||
@@:
|
||||
invlpg [ebx] ; when we start using
|
||||
call free_page ; empty c-o-w page instead this ?
|
||||
@@:
|
||||
add ebx, 4096 ; PAGESIZE?
|
||||
.next:
|
||||
add ebx, 4096
|
||||
add edx, 4
|
||||
dec ecx
|
||||
jnz .unmap
|
||||
|
||||
pop eax ; .num_released_pages
|
||||
pop ebx
|
||||
or al, 1 ; return non zero on success
|
||||
shl eax, 12
|
||||
mov ecx, [current_process]
|
||||
sub [ecx+PROC.mem_used], eax
|
||||
push eax
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
pop eax ; return number of released bytes
|
||||
ret
|
||||
.error:
|
||||
pop ebx
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
xor eax, eax ; something wrong
|
||||
dec eax
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
user_normalize:
|
||||
; in: esi=heap_base, edi=heap_top
|
||||
proc user_normalize uses esi edi
|
||||
; in: edx->PROC
|
||||
; out: eax=0 <=> OK
|
||||
; destroys: ebx,edx,esi,edi
|
||||
; destroys: ebx,edx
|
||||
mov esi, dword [edx+PROC.heap_base]
|
||||
mov edi, dword [edx+PROC.heap_top]
|
||||
shr esi, 12
|
||||
shr edi, 12
|
||||
@@:
|
||||
@ -959,6 +989,7 @@ user_normalize:
|
||||
.err:
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
user_realloc:
|
||||
; in: eax = pointer, ebx = new size
|
||||
@ -1004,37 +1035,43 @@ user_realloc:
|
||||
cmp edx, ebx
|
||||
jb .realloc_add
|
||||
; release part of allocated memory
|
||||
push edx
|
||||
push 0
|
||||
virtual at esp
|
||||
.num_released_pages dd ?
|
||||
end virtual
|
||||
.loop:
|
||||
cmp edx, ebx
|
||||
jz .release_done
|
||||
dec edx
|
||||
xor eax, eax
|
||||
xchg eax, [page_tabs + edx*4]
|
||||
test al, 1
|
||||
jz .loop
|
||||
call free_page
|
||||
push dword [page_tabs + edx*4]
|
||||
mov dword [page_tabs + edx*4], 0
|
||||
mov eax, edx
|
||||
shl eax, 12
|
||||
invlpg [eax]
|
||||
pop eax
|
||||
test al, 1
|
||||
jz .loop
|
||||
inc [.num_released_pages]
|
||||
test eax, PG_SHARED
|
||||
jnz .loop
|
||||
call free_page
|
||||
jmp .loop
|
||||
.release_done:
|
||||
pop eax ; .num_released_pages
|
||||
mov edx, [current_process]
|
||||
shl eax, 12
|
||||
sub [edx+PROC.mem_used], eax
|
||||
pop edx
|
||||
sub ebx, ecx
|
||||
cmp ebx, 1
|
||||
jnz .nofreeall
|
||||
mov eax, [page_tabs + ecx*4]
|
||||
and eax, not 0xFFF
|
||||
mov edx, [current_process]
|
||||
mov ebx, [edx + PROC.mem_used]
|
||||
sub ebx, eax
|
||||
add ebx, 0x1000
|
||||
or al, MEM_BLOCK_FREE
|
||||
mov [page_tabs + ecx*4], eax
|
||||
push esi edi
|
||||
mov esi, [edx + PROC.heap_base]
|
||||
mov edi, [edx + PROC.heap_top]
|
||||
mov [edx + PROC.mem_used], ebx
|
||||
mov edx, [current_process]
|
||||
call user_normalize
|
||||
pop edi esi
|
||||
jmp .ret0 ; all freed
|
||||
.nofreeall:
|
||||
sub edx, ecx
|
||||
@ -1043,13 +1080,6 @@ user_realloc:
|
||||
xchg [page_tabs + ecx*4], ebx
|
||||
shr ebx, 12
|
||||
sub ebx, edx
|
||||
push ebx ecx edx
|
||||
mov edx, [current_process]
|
||||
shl ebx, 12
|
||||
sub ebx, [edx + PROC.mem_used]
|
||||
neg ebx
|
||||
mov [edx + PROC.mem_used], ebx
|
||||
pop edx ecx ebx
|
||||
lea eax, [ecx + 1]
|
||||
shl eax, 12
|
||||
push eax
|
||||
@ -1119,9 +1149,6 @@ user_realloc:
|
||||
cld
|
||||
rep stosd
|
||||
pop edi
|
||||
mov edx, [current_process]
|
||||
shl ebx, 12
|
||||
add [edx + PROC.mem_used], ebx
|
||||
|
||||
mov ecx, [current_process]
|
||||
lea ecx, [ecx + PROC.heap_lock]
|
||||
@ -1195,11 +1222,6 @@ user_realloc:
|
||||
dec edx
|
||||
jnz @b
|
||||
.no:
|
||||
push ebx
|
||||
mov edx, [current_process]
|
||||
shl ebx, 12
|
||||
add [edx + PROC.mem_used], ebx
|
||||
pop ebx
|
||||
@@:
|
||||
mov dword [page_tabs + esi*4], MEM_BLOCK_RESERVED
|
||||
inc esi
|
||||
@ -1218,24 +1240,47 @@ user_realloc:
|
||||
|
||||
|
||||
; param
|
||||
; eax= shm_map object
|
||||
|
||||
align 4
|
||||
destroy_smap:
|
||||
|
||||
pushfd
|
||||
cli
|
||||
; edi= shm_map object
|
||||
; [esp+4] = process
|
||||
|
||||
proc destroy_smap ;stdcall, process:dword
|
||||
push esi
|
||||
push edi
|
||||
mov esi, [edi+SMAP.parent]
|
||||
cmp [edi+SMAP.type], SMAP_TYPE_SMEM
|
||||
jz .smem
|
||||
mov ecx, [esp+8]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_lock
|
||||
stdcall release_pemap, [esp+8]
|
||||
mov ecx, [esp+8]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
sub ecx, PROC.heap_lock
|
||||
cmp ecx, [current_process]
|
||||
jnz @f
|
||||
stdcall user_free, [edi+SMAP.base]
|
||||
@@:
|
||||
call dereference_pe
|
||||
jmp .common
|
||||
.smem:
|
||||
mov eax, [current_process]
|
||||
cmp [esp+8], eax
|
||||
jnz @f
|
||||
stdcall user_free, [edi+SMAP.base]
|
||||
@@:
|
||||
call dereference_smem
|
||||
.common:
|
||||
mov eax, edi
|
||||
call free
|
||||
pop esi
|
||||
ret 4
|
||||
endp
|
||||
|
||||
mov edi, eax
|
||||
mov esi, [eax + SMAP.parent]
|
||||
test esi, esi
|
||||
jz .done
|
||||
|
||||
lock dec [esi + SMEM.refcount]
|
||||
jnz .done
|
||||
proc dereference_smem
|
||||
mov ecx, shmem_list_mutex
|
||||
call mutex_lock
|
||||
dec [esi+SMEM.refcount]
|
||||
jnz mutex_unlock
|
||||
|
||||
mov ecx, [esi + SMEM.bk]
|
||||
mov edx, [esi + SMEM.fd]
|
||||
@ -1243,18 +1288,14 @@ destroy_smap:
|
||||
mov [ecx + SMEM.fd], edx
|
||||
mov [edx + SMEM.bk], ecx
|
||||
|
||||
mov ecx, shmem_list_mutex
|
||||
call mutex_unlock
|
||||
|
||||
stdcall kernel_free, [esi + SMEM.base]
|
||||
mov eax, esi
|
||||
call free
|
||||
.done:
|
||||
mov eax, edi
|
||||
call destroy_kernel_object
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
popfd
|
||||
|
||||
ret
|
||||
endp
|
||||
|
||||
E_NOTFOUND = 5
|
||||
E_ACCESS = 10
|
||||
@ -1273,31 +1314,28 @@ SHM_CREATE = 2 shl 2
|
||||
SHM_OPEN_MASK = 3 shl 2
|
||||
|
||||
align 4
|
||||
proc shmem_open stdcall name:dword, size:dword, access:dword
|
||||
proc shmem_open stdcall uses ebx esi edi, name:dword, size:dword, access:dword
|
||||
locals
|
||||
action dd ?
|
||||
owner_access dd ?
|
||||
mapped dd ?
|
||||
edx_ret dd ?
|
||||
endl
|
||||
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov [mapped], 0
|
||||
mov [owner_access], 0
|
||||
|
||||
pushfd ;mutex required
|
||||
cli
|
||||
|
||||
mov eax, [access]
|
||||
and eax, SHM_OPEN_MASK
|
||||
mov [action], eax
|
||||
|
||||
mov ebx, [name]
|
||||
test ebx, ebx
|
||||
mov edx, E_PARAM
|
||||
jz .fail
|
||||
mov [edx_ret], E_PARAM
|
||||
jz .exit
|
||||
|
||||
mov ecx, shmem_list_mutex
|
||||
call mutex_lock
|
||||
|
||||
mov esi, [shmem_list.fd]
|
||||
align 4
|
||||
@ -1316,22 +1354,22 @@ align 4
|
||||
.not_found:
|
||||
mov eax, [action]
|
||||
|
||||
mov [edx_ret], E_NOTFOUND
|
||||
cmp eax, SHM_OPEN
|
||||
mov edx, E_NOTFOUND
|
||||
je .fail
|
||||
je .exit_unlock
|
||||
|
||||
mov [edx_ret], E_PARAM
|
||||
cmp eax, SHM_CREATE
|
||||
mov edx, E_PARAM
|
||||
je .create_shm
|
||||
|
||||
cmp eax, SHM_OPEN_ALWAYS
|
||||
jne .fail
|
||||
jne .exit_unlock
|
||||
|
||||
.create_shm:
|
||||
|
||||
mov ecx, [size]
|
||||
test ecx, ecx
|
||||
jz .fail
|
||||
jz .exit_unlock
|
||||
|
||||
add ecx, 4095
|
||||
and ecx, -4096
|
||||
@ -1341,13 +1379,11 @@ align 4
|
||||
call malloc
|
||||
test eax, eax
|
||||
mov esi, eax
|
||||
mov edx, E_NOMEM
|
||||
jz .fail
|
||||
mov [edx_ret], E_NOMEM
|
||||
jz .exit_unlock
|
||||
|
||||
stdcall kernel_alloc, [size]
|
||||
test eax, eax
|
||||
mov [mapped], eax
|
||||
mov edx, E_NOMEM
|
||||
jz .cleanup
|
||||
|
||||
mov ecx, [size]
|
||||
@ -1376,16 +1412,16 @@ align 4
|
||||
.found:
|
||||
mov eax, [action]
|
||||
|
||||
mov [edx_ret], E_ACCESS
|
||||
cmp eax, SHM_CREATE
|
||||
mov edx, E_ACCESS
|
||||
je .exit
|
||||
je .exit_unlock
|
||||
|
||||
mov [edx_ret], E_PARAM
|
||||
cmp eax, SHM_OPEN
|
||||
mov edx, E_PARAM
|
||||
je .create_map
|
||||
|
||||
cmp eax, SHM_OPEN_ALWAYS
|
||||
jne .fail
|
||||
jne .exit_unlock
|
||||
|
||||
.create_map:
|
||||
|
||||
@ -1393,129 +1429,148 @@ align 4
|
||||
and eax, SHM_ACCESS_MASK
|
||||
cmp eax, [esi + SMEM.access]
|
||||
mov [access], eax
|
||||
mov edx, E_ACCESS
|
||||
ja .fail
|
||||
mov [edx_ret], E_ACCESS
|
||||
ja .exit_unlock
|
||||
|
||||
inc [esi+SMEM.refcount]
|
||||
mov ecx, shmem_list_mutex
|
||||
call mutex_unlock
|
||||
|
||||
mov ebx, [current_slot_idx]
|
||||
shl ebx, BSF sizeof.TASKDATA
|
||||
mov ebx, [TASK_TABLE + ebx + TASKDATA.pid]
|
||||
mov eax, sizeof.SMAP
|
||||
|
||||
call create_kernel_object
|
||||
call malloc
|
||||
test eax, eax
|
||||
mov edi, eax
|
||||
mov edx, E_NOMEM
|
||||
jz .fail
|
||||
|
||||
inc [esi + SMEM.refcount]
|
||||
|
||||
mov [edi + SMAP.magic], 'SMAP'
|
||||
mov [edi + SMAP.destroy], destroy_smap
|
||||
mov [edi + SMAP.parent], esi
|
||||
mov [edi + SMAP.base], 0
|
||||
|
||||
stdcall user_alloc, [esi + SMEM.size]
|
||||
test eax, eax
|
||||
mov [mapped], eax
|
||||
mov edx, E_NOMEM
|
||||
mov [edx_ret], E_NOMEM
|
||||
jz .cleanup2
|
||||
|
||||
mov [edi+SMAP.type], SMAP_TYPE_SMEM
|
||||
mov [edi + SMAP.parent], esi
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_lock
|
||||
|
||||
stdcall user_alloc_nolock, [esi+SMEM.size]
|
||||
test eax, eax
|
||||
mov [mapped], eax
|
||||
jz .cleanup3
|
||||
|
||||
mov [edi + SMAP.base], eax
|
||||
mov ecx, [current_process]
|
||||
mov edx, [ecx+PROC.smap_list+SMAP.bk]
|
||||
add ecx, PROC.smap_list
|
||||
mov [edi+SMAP.fd], ecx
|
||||
mov [edi+SMAP.bk], edx
|
||||
mov [ecx+SMAP.bk], edi
|
||||
mov [edx+SMAP.fd], edi
|
||||
|
||||
mov ecx, [esi + SMEM.size]
|
||||
mov [size], ecx
|
||||
mov [edi + SMAP.size], ecx
|
||||
mov [edx_ret], ecx
|
||||
|
||||
shr ecx, 12
|
||||
shr eax, 10
|
||||
|
||||
mov esi, [esi + SMEM.base]
|
||||
shr esi, 10
|
||||
lea edi, [page_tabs + eax]
|
||||
add esi, page_tabs
|
||||
|
||||
xor ebx, ebx
|
||||
mov edx, [access]
|
||||
or edx, [owner_access]
|
||||
shl edx, 1
|
||||
or edx, PG_SHARED + PG_UR
|
||||
@@:
|
||||
lodsd
|
||||
and eax, 0xFFFFF000
|
||||
or eax, edx
|
||||
stosd
|
||||
loop @B
|
||||
mov edi, [page_tabs+esi+ebx*4]
|
||||
and edi, 0xFFFFF000
|
||||
or edi, edx
|
||||
mov [page_tabs+eax+ebx*4], edi
|
||||
inc ebx
|
||||
dec ecx
|
||||
jnz @B
|
||||
|
||||
xor edx, edx
|
||||
mov ecx, [current_process]
|
||||
shl ebx, 12
|
||||
add [ecx+PROC.mem_used], ebx
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
|
||||
cmp [owner_access], 0
|
||||
jne .fail
|
||||
.exit:
|
||||
mov edx, [size]
|
||||
.fail:
|
||||
mov eax, [mapped]
|
||||
jz .exit
|
||||
mov [edx_ret], 0
|
||||
|
||||
popfd
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
.exit:
|
||||
mov eax, [mapped]
|
||||
mov edx, [edx_ret]
|
||||
ret
|
||||
.cleanup:
|
||||
mov [size], edx
|
||||
mov eax, esi
|
||||
call free
|
||||
.exit_unlock:
|
||||
mov ecx, shmem_list_mutex
|
||||
call mutex_unlock
|
||||
jmp .exit
|
||||
|
||||
.cleanup2:
|
||||
mov [size], edx
|
||||
.cleanup3:
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
mov eax, edi
|
||||
call destroy_smap
|
||||
call free
|
||||
.cleanup2:
|
||||
call dereference_smem
|
||||
jmp .exit
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc shmem_close stdcall, name:dword
|
||||
|
||||
mov eax, [name]
|
||||
test eax, eax
|
||||
cmp [name], 0
|
||||
jz .fail
|
||||
|
||||
push esi
|
||||
push edi
|
||||
pushfd
|
||||
cli
|
||||
|
||||
mov esi, [current_slot]
|
||||
add esi, APP_OBJ_OFFSET
|
||||
mov ecx, [current_process]
|
||||
lea edi, [ecx+PROC.smap_list]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_lock
|
||||
mov esi, edi
|
||||
|
||||
.next:
|
||||
mov eax, [esi + APPOBJ.fd]
|
||||
test eax, eax
|
||||
jz @F
|
||||
mov edi, [edi+SMAP.fd]
|
||||
cmp edi, esi
|
||||
je .notfound
|
||||
|
||||
cmp eax, esi
|
||||
mov esi, eax
|
||||
je @F
|
||||
|
||||
cmp [eax + SMAP.magic], 'SMAP'
|
||||
cmp [edi + SMAP.type], SMAP_TYPE_SMEM
|
||||
jne .next
|
||||
|
||||
mov edi, [eax + SMAP.parent]
|
||||
test edi, edi
|
||||
jz .next
|
||||
mov eax, [edi + SMAP.parent]
|
||||
add eax, SMEM.name
|
||||
|
||||
lea edi, [edi + SMEM.name]
|
||||
stdcall strncmp, [name], edi, 32
|
||||
stdcall strncmp, [name], eax, 32
|
||||
test eax, eax
|
||||
jne .next
|
||||
|
||||
stdcall user_free, [esi + SMAP.base]
|
||||
mov eax, [edi+SMAP.fd]
|
||||
mov edx, [edi+SMAP.bk]
|
||||
mov [eax+SMAP.bk], edx
|
||||
mov [edx+SMAP.fd], eax
|
||||
|
||||
mov eax, esi
|
||||
call [esi + APPOBJ.destroy]
|
||||
@@:
|
||||
popfd
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
|
||||
stdcall destroy_smap, [current_process]
|
||||
|
||||
.exit:
|
||||
pop edi
|
||||
pop esi
|
||||
.fail:
|
||||
ret
|
||||
.notfound:
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
jmp .exit
|
||||
endp
|
||||
|
||||
|
||||
@ -1586,4 +1641,4 @@ endl
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
endp
|
||||
endp
|
||||
|
File diff suppressed because it is too large
Load Diff
833
kernel/branches/kolibrios-pe-clevermouse/core/peuser.inc
Normal file
833
kernel/branches/kolibrios-pe-clevermouse/core/peuser.inc
Normal file
@ -0,0 +1,833 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2016. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Checks whether the given file is already loaded as PE.
|
||||
; If so, returns pointer to PEDESCR which can be used for map_pe_usermode.
|
||||
; out: eax = 0, ebx undefined
|
||||
; out: esi -> PEDESCR
|
||||
; If not, loads the given file; if it is PE, creates PEDESCR;
|
||||
; out: eax -> file data, ebx = file size
|
||||
; out: esi -> PEDESCR
|
||||
; if it is not PE, returns loaded file as is.
|
||||
; out: eax -> file data, ebx = file size
|
||||
; out: esi = 0
|
||||
; On error:
|
||||
; out: eax = negative error code, ebx = 0
|
||||
; out: esi = 0
|
||||
proc load_file_maybe_pe stdcall uses edi, file_name:dword
|
||||
locals
|
||||
fileinfo rb 40
|
||||
filedata dd ?
|
||||
defaultbase dd ?
|
||||
entry dd ?
|
||||
stacksize dd ?
|
||||
endl
|
||||
and [filedata], 0
|
||||
; 1. Lock the common mutex for PE list.
|
||||
mov ecx, pe_list_mutex
|
||||
call mutex_lock
|
||||
; 2. Check whether this PE file is already mapped somewhere.
|
||||
; 2a. Get the timestamp. If failed, pass filesystem error to the caller.
|
||||
lea eax, [fileinfo]
|
||||
stdcall get_fileinfo, [file_name], eax
|
||||
mov edi, eax
|
||||
neg edi
|
||||
jnz .fail_unlock
|
||||
; 2b. Scan the list of PE files, for each file compare timestamp and name.
|
||||
; If all parameters match, go to 6. Otherwide, proceed to 3.
|
||||
mov esi, [pe_list.fd]
|
||||
.scan_existing:
|
||||
cmp esi, pe_list
|
||||
jz .load_new
|
||||
mov eax, dword [fileinfo+24]; last modified time
|
||||
mov edx, dword [fileinfo+28]; last modified date
|
||||
cmp dword [esi+PEDESCR.timestamp], eax
|
||||
jnz .continue_scan
|
||||
cmp dword [esi+PEDESCR.timestamp+4], edx
|
||||
jnz .continue_scan
|
||||
stdcall strncmp, [esi+PEDESCR.name], [file_name], -1
|
||||
test eax, eax
|
||||
jz .already_loaded
|
||||
.continue_scan:
|
||||
mov esi, [esi+PEDESCR.fd]
|
||||
jmp .scan_existing
|
||||
|
||||
; Either this file is not PE, or it has not been mapped yet.
|
||||
.load_new:
|
||||
; 3. Load and unpack file data.
|
||||
; If failed, return -5 "file not found".
|
||||
stdcall load_file, [file_name]
|
||||
movi edi, -5
|
||||
test eax, eax
|
||||
jz .fail_unlock
|
||||
mov [filedata], eax
|
||||
mov dword [fileinfo+32], ebx
|
||||
; 4. Check that the file is valid PE, has image data and is not too large.
|
||||
; If not, pass the loaded file to the caller as is.
|
||||
cmp ebx, 40h
|
||||
jb .not_pe
|
||||
cmp word [eax], 'MZ'
|
||||
jz .check_mz
|
||||
cmp [eax+STRIPPED_PE_HEADER.Signature], STRIPPED_PE_SIGNATURE
|
||||
jnz .not_pe
|
||||
mov ecx, [eax+STRIPPED_PE_HEADER.SizeOfStackReserve]
|
||||
mov [stacksize], ecx
|
||||
mov ecx, [eax+STRIPPED_PE_HEADER.ImageBase]
|
||||
mov esi, [eax+STRIPPED_PE_HEADER.SizeOfImage]
|
||||
mov edi, [eax+STRIPPED_PE_HEADER.AddressOfEntryPoint]
|
||||
jmp .pe
|
||||
.check_mz:
|
||||
mov ecx, [eax+3Ch]
|
||||
add eax, ecx
|
||||
add ecx, IMAGE_NT_HEADERS.OptionalHeader
|
||||
jc .not_pe
|
||||
cmp ecx, ebx
|
||||
ja .not_pe
|
||||
cmp [eax+IMAGE_NT_HEADERS.Signature], 'PE'
|
||||
jnz .not_pe
|
||||
movzx edx, [eax+IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader]
|
||||
cmp edx, IMAGE_OPTIONAL_HEADER32.DataDirectory
|
||||
jb .not_pe
|
||||
add ecx, edx
|
||||
jc .not_pe
|
||||
cmp ecx, ebx
|
||||
ja .not_pe
|
||||
cmp [eax+IMAGE_NT_HEADERS.OptionalHeader.Magic], 10Bh
|
||||
jnz .not_pe
|
||||
mov ecx, [eax+IMAGE_NT_HEADERS.OptionalHeader.SizeOfStackReserve]
|
||||
mov [stacksize], ecx
|
||||
mov ecx, [eax+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
|
||||
mov esi, [eax+IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage]
|
||||
mov edi, [eax+IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint]
|
||||
.pe:
|
||||
test esi, esi
|
||||
jz .not_pe
|
||||
cmp esi, 16*1024*1024
|
||||
ja .not_pe
|
||||
mov [defaultbase], ecx
|
||||
mov [entry], edi
|
||||
add esi, 0xFFF
|
||||
shr esi, 12
|
||||
; 5. Allocate and initialize PEDESCR structure.
|
||||
; 5a. Calculate structure size: sizeof.PEDESCR + dword per image page + size of PE name.
|
||||
mov edi, [file_name]
|
||||
mov ecx, -1
|
||||
xor eax, eax
|
||||
repnz scasb
|
||||
not ecx
|
||||
lea eax, [ecx+esi*4+sizeof.PEDESCR]
|
||||
; 5b. Allocate memory.
|
||||
; If failed, return -30 "no memory".
|
||||
push ecx
|
||||
call malloc
|
||||
pop ecx
|
||||
movi edi, -30
|
||||
test eax, eax
|
||||
jz .fail_and_free_data
|
||||
; 5c. Initialize PEDESCR structure.
|
||||
mov [eax+PEDESCR.size], esi
|
||||
lea edi, [eax+esi*4+sizeof.PEDESCR]
|
||||
mov esi, [file_name]
|
||||
mov [eax+PEDESCR.name], edi
|
||||
rep movsb
|
||||
mov esi, eax
|
||||
lea edi, [eax+sizeof.PEDESCR]
|
||||
mov ecx, [eax+PEDESCR.size]
|
||||
xor eax, eax
|
||||
rep stosd
|
||||
mov eax, dword [fileinfo+24]
|
||||
mov dword [esi+PEDESCR.timestamp], eax
|
||||
mov eax, dword [fileinfo+28]
|
||||
mov dword [esi+PEDESCR.timestamp+4], eax
|
||||
mov eax, [defaultbase]
|
||||
mov [esi+PEDESCR.defaultbase], eax
|
||||
mov eax, [entry]
|
||||
mov [esi+PEDESCR.entry], eax
|
||||
mov eax, [stacksize]
|
||||
mov [esi+PEDESCR.stacksize], eax
|
||||
and dword [esi+PEDESCR.refcount], 0; no SMAPs yet; later it will be incremented
|
||||
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||
call mutex_init
|
||||
; 5d. Insert PEDESCR structure in tail of the common list.
|
||||
mov [esi+PEDESCR.fd], pe_list
|
||||
mov eax, [pe_list.bk]
|
||||
mov [pe_list.bk], esi
|
||||
mov [esi+PEDESCR.bk], eax
|
||||
mov [eax+PEDESCR.fd], esi
|
||||
.already_loaded:
|
||||
; We have got the PEDESCR structure,
|
||||
; either already-existed from step 2 or created at step 5.
|
||||
; In the last case we have also got the file data,
|
||||
; in the first case [filedata] is still zero.
|
||||
; 6. Increment reference counter in PEDESCR structure.
|
||||
inc [esi+PEDESCR.refcount]
|
||||
; 7. Release the common mutex for PE list.
|
||||
; We have got a new reference to our PEDESCR, it will not go away unexpectedly.
|
||||
mov ecx, pe_list_mutex
|
||||
call mutex_unlock
|
||||
mov eax, [filedata]
|
||||
mov ebx, dword [fileinfo+32]
|
||||
ret
|
||||
.fail_and_free_data:
|
||||
stdcall kernel_free, [filedata]
|
||||
.fail_unlock:
|
||||
mov ecx, pe_list_mutex
|
||||
call mutex_unlock
|
||||
.fail:
|
||||
mov eax, edi
|
||||
xor ebx, ebx
|
||||
xor esi, esi
|
||||
ret
|
||||
.not_pe:
|
||||
mov ecx, pe_list_mutex
|
||||
call mutex_unlock
|
||||
mov eax, [filedata]
|
||||
xor esi, esi
|
||||
ret
|
||||
endp
|
||||
|
||||
proc map_pe_usermode stdcall uses ebx esi edi, descr:dword, filedata:dword, filesize:dword
|
||||
locals
|
||||
img_base dd ?
|
||||
peheader dd ?
|
||||
header_size dd ?
|
||||
num_sections dd ?
|
||||
sections dd ?
|
||||
section_idx dd ?
|
||||
page_index dd ?
|
||||
page_offset dd ?
|
||||
cur_page dd ?
|
||||
cur_access db ?
|
||||
rb 3
|
||||
pages dd ?
|
||||
num_allocated_pages dd ?
|
||||
endl
|
||||
|
||||
; 1. Basic preparations.
|
||||
; 1a. Check that the process heap has been initialized.
|
||||
; Return -30 "no memory" if not.
|
||||
mov esi, [descr]
|
||||
movi edi, -30
|
||||
mov eax, [current_process]
|
||||
cmp [eax+PROC.heap_top], 0
|
||||
jz .fail_dereference
|
||||
; 1b. If filedata is passed, fill the required fields from header now.
|
||||
mov eax, [filedata]
|
||||
mov ebx, [filesize]
|
||||
dec edi ; -30 -> -31
|
||||
test eax, eax
|
||||
jz @f
|
||||
call .validate_header
|
||||
jc .fail_dereference
|
||||
@@:
|
||||
|
||||
; 2. Generate array of pages for mapping in address space in the process.
|
||||
; It is possible to join this step with step 13, avoiding temporary allocation
|
||||
; and putting the result directly in the page table, but that would require
|
||||
; doing potentially long operations like loading/unpacking the file
|
||||
; while holding address space lock, which could block other threads
|
||||
; that just want to lazy-allocate their zero-only pages not related to PE.
|
||||
; So, keep generating and mapping separate.
|
||||
; 2a. Allocate memory.
|
||||
inc edi ; -31 -> -30
|
||||
mov eax, [esi+PEDESCR.size]
|
||||
shl eax, 2
|
||||
call malloc
|
||||
test eax, eax
|
||||
jz .fail_dereference
|
||||
mov [pages], eax
|
||||
; 2b. Acquire the lock.
|
||||
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||
call mutex_lock
|
||||
; 2c. Prepare for loop over pages: set page index and page offset to zero.
|
||||
xor ecx, ecx
|
||||
mov [page_index], ecx
|
||||
mov [page_offset], ecx
|
||||
mov [num_allocated_pages], ecx
|
||||
.fill_pages:
|
||||
; 2d. For each page, test whether we need to regenerate it.
|
||||
; Pages that need to be regenerated are marked as zero in pages array.
|
||||
mov eax, [esi+sizeof.PEDESCR+ecx*4]
|
||||
test eax, eax
|
||||
jz .create_page
|
||||
; 2e. For each page that we do not need to regenerate,
|
||||
; increment reference counter if it is less than 0xFF
|
||||
; and go to 2t.
|
||||
lea edx, [eax+1]
|
||||
test edx, 0xFF
|
||||
jz .page_created
|
||||
mov [esi+sizeof.PEDESCR+ecx*4], edx
|
||||
jmp .page_created
|
||||
.create_page:
|
||||
; 2f. If the file has not been already loaded/unpacked,
|
||||
; do it now, validating the content.
|
||||
cmp [filedata], 0
|
||||
jnz @f
|
||||
stdcall load_file, [esi+PEDESCR.name]
|
||||
test eax, eax
|
||||
jz .fail_free_pages
|
||||
call .validate_header
|
||||
jc .fail_free_pages
|
||||
@@:
|
||||
; 2h. Initialize for generating a page:
|
||||
; do not allocate a page until we will be sure that data are present,
|
||||
; there are no access rights yet.
|
||||
and [cur_page], 0
|
||||
mov [cur_access], 0
|
||||
; 2i. Check whether the page overlaps file header.
|
||||
; If not, go to 2m.
|
||||
mov eax, [page_offset]
|
||||
cmp eax, [header_size]
|
||||
jae .no_header
|
||||
; 2j. Allocate the page data.
|
||||
stdcall kernel_alloc, 0x1000
|
||||
test eax, eax
|
||||
jz .fail_free_pages
|
||||
mov [cur_page], eax
|
||||
; 2k. Set access rights for header: readonly; copy header data.
|
||||
mov [cur_access], IMAGE_SCN_MEM_READ shr 28
|
||||
mov esi, [filedata]
|
||||
mov edi, eax
|
||||
add esi, [page_offset]
|
||||
mov ecx, [header_size]
|
||||
sub ecx, [page_offset]
|
||||
cmp ecx, 0x1000
|
||||
jb @f
|
||||
mov ecx, 0x1000
|
||||
@@:
|
||||
mov edx, ecx
|
||||
shr ecx, 2
|
||||
rep movsd
|
||||
mov ecx, edx
|
||||
and ecx, 3
|
||||
rep movsb
|
||||
; 2l. Fill the rest of the page with zeroes.
|
||||
mov ecx, 0x1000
|
||||
sub ecx, edx
|
||||
mov edx, ecx
|
||||
shr ecx, 2
|
||||
and edx, 3
|
||||
xor eax, eax
|
||||
rep stosd
|
||||
mov ecx, edx
|
||||
rep stosb
|
||||
.no_header:
|
||||
; 2m. Prepare for loop over sections.
|
||||
; Skip the loop if there are no sections.
|
||||
mov eax, [num_sections]
|
||||
mov ebx, [sections]
|
||||
test eax, eax
|
||||
jz .no_sections
|
||||
mov [section_idx], eax
|
||||
.sections_loop:
|
||||
; 2n. For every section, check whether it has data overlapped with
|
||||
; the current page; if so, allocate the page if not yet, copy the data
|
||||
; and fill rest of page with zeroes.
|
||||
; If data are present, there can be two cases:
|
||||
; - the current page has data from the beginning,
|
||||
; - first byte of the current page is not covered by the section.
|
||||
; The first case is typical, the second case is rare.
|
||||
; If the page has not been allocated yet, we can optimize by storing zeroes
|
||||
; only in areas that are not covered by the current section.
|
||||
; However, this becomes twisted in the second case,
|
||||
; so don't bother to optimize the rare case.
|
||||
cmp [ebx+COFF_SECTION.SizeOfRawData], 0
|
||||
jz .section_data_done
|
||||
mov esi, [page_offset]
|
||||
sub esi, [ebx+COFF_SECTION.VirtualAddress]
|
||||
cmp esi, [ebx+COFF_SECTION.SizeOfRawData]
|
||||
jb .beginning_inside
|
||||
add esi, 1000h
|
||||
jnc .section_data_done
|
||||
jz .section_data_done
|
||||
; Rare case: there is an overlap, but the first byte is not covered.
|
||||
; If the page has not been allocated, allocate it now and store 4K zeroes.
|
||||
cmp [cur_page], 0
|
||||
jnz @f
|
||||
stdcall kernel_alloc, 0x1000
|
||||
test eax, eax
|
||||
jz .fail_free_pages
|
||||
mov [cur_page], eax
|
||||
mov edi, eax
|
||||
xor eax, eax
|
||||
mov ecx, 0x1000/4
|
||||
rep stosd
|
||||
@@:
|
||||
mov edi, [ebx+COFF_SECTION.VirtualAddress]
|
||||
and edi, 0xFFF
|
||||
xor esi, esi
|
||||
.copy_data:
|
||||
mov eax, [ebx+COFF_SECTION.SizeOfRawData]
|
||||
sub eax, esi
|
||||
mov ecx, 0x1000
|
||||
sub ecx, edi
|
||||
add edi, [cur_page]
|
||||
cmp ecx, eax
|
||||
jb @f
|
||||
mov ecx, eax
|
||||
@@:
|
||||
add esi, [filedata]
|
||||
add esi, [ebx+COFF_SECTION.PtrRawData]
|
||||
mov edx, ecx
|
||||
shr ecx, 2
|
||||
and edx, 3
|
||||
rep movsd
|
||||
mov ecx, edx
|
||||
rep movsb
|
||||
jmp .section_data_done
|
||||
.beginning_inside:
|
||||
; Normal case: do not store zeroes which will be immediately overwritten.
|
||||
xor edi, edi
|
||||
cmp [cur_page], edi
|
||||
jnz .copy_data
|
||||
stdcall kernel_alloc, 0x1000
|
||||
test eax, eax
|
||||
jz .fail_free_pages
|
||||
mov [cur_page], eax
|
||||
mov edi, eax
|
||||
mov ecx, [ebx+COFF_SECTION.SizeOfRawData]
|
||||
sub ecx, esi
|
||||
cmp ecx, 0x1000
|
||||
jb @f
|
||||
mov ecx, 0x1000
|
||||
@@:
|
||||
add esi, [filedata]
|
||||
add esi, [ebx+COFF_SECTION.PtrRawData]
|
||||
mov edx, ecx
|
||||
shr ecx, 2
|
||||
rep movsd
|
||||
mov ecx, edx
|
||||
and ecx, 3
|
||||
rep movsb
|
||||
mov ecx, 0x1000
|
||||
sub ecx, edx
|
||||
mov edx, ecx
|
||||
shr ecx, 2
|
||||
and edx, 3
|
||||
xor eax, eax
|
||||
rep stosd
|
||||
mov ecx, edx
|
||||
rep stosb
|
||||
.section_data_done:
|
||||
; 2o. Get size of the section header.
|
||||
; Characteristics is the last dword in both
|
||||
; COFF_SECTION and STRIPPED_PE_SECTION, so this helps to access it.
|
||||
movi ecx, sizeof.STRIPPED_PE_SECTION
|
||||
cmp [peheader], 0
|
||||
jz @f
|
||||
mov cl, sizeof.COFF_SECTION
|
||||
@@:
|
||||
; 2p. If the current page intersects virtual address range of the section,
|
||||
; update access rights using section access rights.
|
||||
cmp [ebx+COFF_SECTION.VirtualSize], 0
|
||||
jz .section_access_done
|
||||
mov esi, [page_offset]
|
||||
sub esi, [ebx+COFF_SECTION.VirtualAddress]
|
||||
cmp esi, [ebx+COFF_SECTION.VirtualSize]
|
||||
jb @f
|
||||
add esi, 0x1000
|
||||
jnc .section_access_done
|
||||
jz .section_access_done
|
||||
@@:
|
||||
mov eax, [ebx+ecx-4]
|
||||
shr eax, 28
|
||||
or [cur_access], al
|
||||
.section_access_done:
|
||||
; 2q. Advance to the next section, while there are sections left.
|
||||
add ebx, ecx
|
||||
dec [section_idx]
|
||||
jnz .sections_loop
|
||||
.no_sections:
|
||||
; 2r. Shareable pages can not be lazy-allocated
|
||||
; even if they only contain uninitialized data.
|
||||
; If the page is shareable and has not been allocated yet, do it now.
|
||||
test [cur_access], IMAGE_SCN_MEM_SHARED shr 28
|
||||
jz @f
|
||||
cmp [cur_page], 0
|
||||
jnz @f
|
||||
stdcall kernel_alloc, 0x1000
|
||||
test eax, eax
|
||||
jz .fail_free_pages
|
||||
mov [cur_page], eax
|
||||
mov edi, eax
|
||||
xor eax, eax
|
||||
mov ecx, 0x1000/4
|
||||
rep stosd
|
||||
@@:
|
||||
; 2s. Get and store the item for page array: 0xFF for pages with zeroes,
|
||||
; physical address of the page plus 1 for reference counter otherwise,
|
||||
; with access rights in bits 8-11 in both cases.
|
||||
mov edi, 0xFF
|
||||
mov eax, [cur_page]
|
||||
test eax, eax
|
||||
jz @f
|
||||
call get_pg_addr
|
||||
lea edi, [eax+1]
|
||||
stdcall free_kernel_space, [cur_page]
|
||||
@@:
|
||||
movzx eax, [cur_access]
|
||||
shl eax, 8
|
||||
or eax, edi
|
||||
mov ecx, [page_index]
|
||||
mov esi, [descr]
|
||||
mov [esi+sizeof.PEDESCR+ecx*4], eax
|
||||
.page_created:
|
||||
; 2t. Transform the item from page array to page table entry:
|
||||
; - drop reference counter,
|
||||
; - map zero-only page to LAZY_ALLOC_PAGE
|
||||
; with optional flags LAZY_ALLOC_{UNREADABLE,UNWRITABLE},
|
||||
; PF handler will lazy-allocate it;
|
||||
; - for pages with data,
|
||||
; map readable and executable to user bit,
|
||||
; for shareable pages map writable to writable bit,
|
||||
; for non-shareable pages ignore writable to support copy-on-write.
|
||||
mov edx, eax
|
||||
and eax, not 0xFFF
|
||||
jz .page_set_zero
|
||||
inc [num_allocated_pages]
|
||||
or eax, PG_READ+PG_SHARED
|
||||
test dh, (IMAGE_SCN_MEM_READ+IMAGE_SCN_MEM_EXECUTE) shr 28
|
||||
jz @f
|
||||
or al, PG_USER
|
||||
@@:
|
||||
test dh, IMAGE_SCN_MEM_SHARED shr 28
|
||||
jz @f
|
||||
test dh, IMAGE_SCN_MEM_WRITE shr 28
|
||||
jz @f
|
||||
or al, PG_WRITE
|
||||
@@:
|
||||
jmp .pte_generated
|
||||
.page_set_zero:
|
||||
mov al, LAZY_ALLOC_PAGE
|
||||
test dh, (IMAGE_SCN_MEM_READ+IMAGE_SCN_MEM_EXECUTE) shr 28
|
||||
jnz @f
|
||||
or al, LAZY_ALLOC_UNREADABLE
|
||||
@@:
|
||||
test dh, IMAGE_SCN_MEM_WRITE shr 28
|
||||
jnz @f
|
||||
or al, LAZY_ALLOC_UNWRITABLE
|
||||
@@:
|
||||
.pte_generated:
|
||||
mov edi, [pages]
|
||||
mov [edi+ecx*4], eax
|
||||
; 2u. Advance to the next page, until PEDESCR.size is reached.
|
||||
inc ecx
|
||||
inc [page_index]
|
||||
add [page_offset], 0x1000
|
||||
cmp ecx, [esi+PEDESCR.size]
|
||||
jb .fill_pages
|
||||
; 2v. Release the lock.
|
||||
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||
call mutex_unlock
|
||||
; 3. Allocate a new SMAP.
|
||||
movi eax, sizeof.SMAP
|
||||
call malloc
|
||||
test eax, eax
|
||||
jz .fail_free_pages_unlocked
|
||||
mov ebx, eax
|
||||
; 4. Lock the address space so that a random PF from other thread
|
||||
; between end of step 5 and beginning of step 7 would not trash anything.
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_lock
|
||||
; 5. Allocate space in the address space.
|
||||
; Prefer PEDESCR.defaultbase, but allow address anywhere else
|
||||
; if allocation at PEDESCR.defaultbase is not possible.
|
||||
mov edi, [esi+PEDESCR.size]
|
||||
shl edi, 12
|
||||
stdcall user_alloc_at_nolock, [esi+PEDESCR.defaultbase], edi
|
||||
test eax, eax
|
||||
jnz @f
|
||||
stdcall user_alloc_nolock, edi
|
||||
test eax, eax
|
||||
jz .user_alloc_failed
|
||||
@@:
|
||||
mov [img_base], eax
|
||||
; 6. Fill SMAP with values and insert it to the list of SMAPs.
|
||||
mov [ebx+SMAP.type], SMAP_TYPE_PE
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.smap_list
|
||||
mov edx, [ecx+SMAP.fd]
|
||||
mov [ebx+SMAP.fd], edx
|
||||
mov [ebx+SMAP.bk], ecx
|
||||
mov [ecx+SMAP.fd], ebx
|
||||
mov [edx+SMAP.bk], ebx
|
||||
mov [ebx+SMAP.base], eax
|
||||
mov [ebx+SMAP.size], edi
|
||||
mov [ebx+SMAP.parent], esi
|
||||
; 7. Copy page table entries prepared at step 2 to the page table.
|
||||
mov edx, eax
|
||||
shr edx, 12
|
||||
mov ecx, [esi+PEDESCR.size]
|
||||
mov esi, [pages]
|
||||
lea edi, [page_tabs+edx*4]
|
||||
rep movsd
|
||||
mov eax, [num_allocated_pages]
|
||||
shl eax, 12
|
||||
; 8. Release the address space lock.
|
||||
mov ecx, [current_process]
|
||||
add [ecx+PROC.mem_used], eax
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
; 9. Cleanup and return allocated address.
|
||||
mov eax, [pages]
|
||||
call free
|
||||
cmp [filedata], 0
|
||||
jz @f
|
||||
stdcall kernel_free, [filedata]
|
||||
@@:
|
||||
mov eax, [img_base]
|
||||
ret
|
||||
.fail_and_free_data:
|
||||
stdcall kernel_free, [filedata]
|
||||
.fail:
|
||||
mov eax, edi
|
||||
ret
|
||||
.user_alloc_failed:
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
mov eax, ebx
|
||||
call free
|
||||
.fail_free_pages_unlocked:
|
||||
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||
call mutex_lock
|
||||
.fail_free_pages:
|
||||
mov ecx, [page_index]
|
||||
test ecx, ecx
|
||||
jz .fail_free_pages_array
|
||||
mov eax, [esi+sizeof.PEDESCR+(ecx-1)*4]
|
||||
mov edx, eax
|
||||
and eax, not 0xFFF
|
||||
jz .fail_free_next
|
||||
and edx, 0xFF
|
||||
cmp edx, 0xFF
|
||||
jz .fail_free_next
|
||||
dec dword [esi+sizeof.PEDESCR+(ecx-1)*4]
|
||||
dec edx
|
||||
jnz .fail_free_next
|
||||
mov [esi+sizeof.PEDESCR+(ecx-1)*4], edx
|
||||
call free_page
|
||||
.fail_free_next:
|
||||
dec [page_index]
|
||||
jmp .fail_free_pages
|
||||
.fail_free_pages_array:
|
||||
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||
call mutex_unlock
|
||||
mov eax, [pages]
|
||||
call free
|
||||
movi edi, -30
|
||||
.fail_dereference:
|
||||
cmp [filedata], 0
|
||||
jz @f
|
||||
stdcall kernel_free, [filedata]
|
||||
@@:
|
||||
call dereference_pe
|
||||
mov eax, edi
|
||||
ret
|
||||
|
||||
.validate_header:
|
||||
mov [filedata], eax
|
||||
cmp ebx, 40h
|
||||
jb .validate_header.error
|
||||
mov [peheader], 0
|
||||
cmp word [eax], STRIPPED_PE_SIGNATURE
|
||||
jz .validate_header.stripped
|
||||
cmp word [eax], 'MZ'
|
||||
jnz .validate_header.error
|
||||
mov ecx, [eax+3Ch]
|
||||
add eax, ecx
|
||||
add ecx, IMAGE_NT_HEADERS.OptionalHeader
|
||||
jc .validate_header.error
|
||||
cmp ecx, ebx
|
||||
ja .validate_header.error
|
||||
cmp [eax+IMAGE_NT_HEADERS.Signature], 'PE'
|
||||
jnz .validate_header.error
|
||||
mov [peheader], eax
|
||||
movzx edx, [eax+IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader]
|
||||
cmp edx, IMAGE_OPTIONAL_HEADER32.DataDirectory
|
||||
jb .validate_header.error
|
||||
add ecx, edx
|
||||
jc .validate_header.error
|
||||
cmp ecx, ebx
|
||||
ja .validate_header.error
|
||||
lea edx, [eax+IMAGE_NT_HEADERS.OptionalHeader+edx]
|
||||
mov [sections], edx
|
||||
movzx edx, [eax+IMAGE_NT_HEADERS.FileHeader.NumberOfSections]
|
||||
mov [num_sections], edx
|
||||
imul edx, sizeof.COFF_SECTION
|
||||
add ecx, edx
|
||||
jc .validate_header.error
|
||||
cmp ecx, ebx
|
||||
ja .validate_header.error
|
||||
mov edx, [eax+IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders]
|
||||
mov [header_size], edx
|
||||
cmp edx, ebx
|
||||
ja .validate_header.error
|
||||
mov edx, [num_sections]
|
||||
mov ecx, [sections]
|
||||
test edx, edx
|
||||
jz .validate_header.sections_ok
|
||||
@@:
|
||||
mov eax, [ecx+COFF_SECTION.PtrRawData]
|
||||
add eax, [ecx+COFF_SECTION.SizeOfRawData]
|
||||
jc .validate_header.error
|
||||
cmp eax, ebx
|
||||
ja .validate_header.error
|
||||
add ecx, sizeof.COFF_SECTION
|
||||
dec edx
|
||||
jnz @b
|
||||
.validate_header.sections_ok:
|
||||
.validate_header.ok:
|
||||
clc
|
||||
retn
|
||||
.validate_header.stripped:
|
||||
movzx ecx, [eax+STRIPPED_PE_HEADER.NumberOfRvaAndSizes]
|
||||
lea ecx, [sizeof.STRIPPED_PE_HEADER+ecx*8]
|
||||
movzx edx, [eax+STRIPPED_PE_HEADER.NumberOfSections]
|
||||
mov [num_sections], edx
|
||||
imul edx, sizeof.STRIPPED_PE_SECTION
|
||||
add edx, ecx
|
||||
cmp edx, ebx
|
||||
ja .validate_header.error
|
||||
mov edx, [eax+STRIPPED_PE_HEADER.SizeOfHeaders]
|
||||
mov [header_size], edx
|
||||
cmp edx, ebx
|
||||
ja .validate_header.error
|
||||
add ecx, eax
|
||||
mov [sections], ecx
|
||||
mov edx, [num_sections]
|
||||
test edx, edx
|
||||
jz .validate_header.stripped.sections_ok
|
||||
@@:
|
||||
mov eax, [ecx+STRIPPED_PE_SECTION.PtrRawData]
|
||||
add eax, [ecx+STRIPPED_PE_SECTION.SizeOfRawData]
|
||||
jc .validate_header.error
|
||||
cmp eax, ebx
|
||||
ja .validate_header.error
|
||||
add ecx, sizeof.STRIPPED_PE_SECTION
|
||||
dec edx
|
||||
jnz @b
|
||||
.validate_header.stripped.sections_ok:
|
||||
clc
|
||||
retn
|
||||
.validate_header.error:
|
||||
stc
|
||||
retn
|
||||
endp
|
||||
|
||||
; in: edi -> SMAP
|
||||
; in: address space lock must be held
|
||||
proc release_pemap stdcall uses ebx esi, process:dword
|
||||
locals
|
||||
num_released_pages dd 0
|
||||
mapped_pagedir dd -1
|
||||
endl
|
||||
mov esi, [edi+SMAP.base]
|
||||
mov ebx, [edi+SMAP.parent]
|
||||
shr esi, 12
|
||||
dec esi
|
||||
add ebx, sizeof.PEDESCR
|
||||
call .get_page_tab_entry
|
||||
mov ecx, [eax]
|
||||
and ecx, not MEM_BLOCK_DONT_FREE
|
||||
mov [eax], ecx
|
||||
shr ecx, 12
|
||||
dec ecx
|
||||
jz .released
|
||||
.release:
|
||||
inc esi
|
||||
call .get_page_tab_entry
|
||||
mov edx, [eax]
|
||||
test dl, 1
|
||||
jz .next
|
||||
test edx, PG_SHARED
|
||||
jz .next
|
||||
mov dword [eax], 0
|
||||
inc [num_released_pages]
|
||||
xor edx, [ebx]
|
||||
test edx, not 0xFFF
|
||||
jnz .next
|
||||
mov edx, [ebx]
|
||||
mov eax, edx
|
||||
and edx, 0xFF
|
||||
cmp edx, 0xFF
|
||||
jz .next
|
||||
dec eax
|
||||
test dword [ebx], IMAGE_SCN_MEM_SHARED shr 20
|
||||
jnz @f
|
||||
test eax, 0xFF
|
||||
jnz @f
|
||||
call free_page
|
||||
xor eax, eax
|
||||
@@:
|
||||
mov [ebx], eax
|
||||
.next:
|
||||
add ebx, 4
|
||||
dec ecx
|
||||
jnz .release
|
||||
mov eax, [num_released_pages]
|
||||
shl eax, 12
|
||||
mov edx, [process]
|
||||
sub [edx+PROC.mem_used], eax
|
||||
cmp [mapped_pagedir], -1
|
||||
jz .released
|
||||
stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
|
||||
.released:
|
||||
ret
|
||||
|
||||
.get_page_tab_entry:
|
||||
mov eax, [process]
|
||||
cmp eax, [current_process]
|
||||
jnz @f
|
||||
lea eax, [page_tabs+esi*4]
|
||||
retn
|
||||
@@:
|
||||
push edx
|
||||
mov edx, esi
|
||||
shr edx, 10
|
||||
cmp edx, [mapped_pagedir]
|
||||
jz @f
|
||||
mov [mapped_pagedir], edx
|
||||
mov eax, [eax+PROC.pdt_0+edx*4]
|
||||
and eax, not 0xFFF
|
||||
stdcall map_page, [tmp_task_ptab], eax, PG_SWR
|
||||
@@:
|
||||
mov eax, [tmp_task_ptab]
|
||||
mov edx, esi
|
||||
and edx, 0x3FF
|
||||
lea eax, [eax+edx*4]
|
||||
pop edx
|
||||
retn
|
||||
endp
|
||||
|
||||
proc unmap_pe_usermode stdcall uses ebx esi edi, address:dword
|
||||
mov ecx, [current_process]
|
||||
lea edi, [ecx+PROC.smap_list]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_lock
|
||||
mov esi, edi
|
||||
mov eax, [address]
|
||||
.scan:
|
||||
mov edi, [edi+SMAP.fd]
|
||||
cmp edi, esi
|
||||
jz .notfound
|
||||
cmp [edi+SMAP.base], eax
|
||||
jnz .scan
|
||||
mov eax, [edi+SMAP.fd]
|
||||
mov edx, [edi+SMAP.bk]
|
||||
mov [eax+SMAP.bk], edx
|
||||
mov [edx+SMAP.fd], eax
|
||||
call mutex_unlock
|
||||
stdcall destroy_smap, [current_process]
|
||||
xor eax, eax
|
||||
ret
|
||||
.notfound:
|
||||
call mutex_unlock
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
@ -307,7 +307,7 @@ show_error_parameters:
|
||||
; incorrect address in the program
|
||||
|
||||
mov eax, [page_tabs+ebx*4]
|
||||
test eax, 2
|
||||
test eax, 1
|
||||
jz .fail ; address not reserved for use. error
|
||||
|
||||
pop ebx
|
||||
|
@ -42,10 +42,30 @@ struct APP_HDR
|
||||
filename_size rd 1
|
||||
cmdline_size rd 1
|
||||
path_string rd 1
|
||||
pedescr rd 1
|
||||
ends
|
||||
|
||||
; Pointer to this structure is passed as the third argument
|
||||
; to usermode PE loader by the kernel.
|
||||
struct kernel_init_data
|
||||
version dw ?
|
||||
flags dw ?
|
||||
syscall_method dd ?
|
||||
; either one of SYSCALL_METHOD_xxx or pointer to procedure
|
||||
exe_base dd ?
|
||||
stack_base dd ?
|
||||
stack_size dd ?
|
||||
exe_path dd ?
|
||||
command_line dd ?
|
||||
environment dd ?
|
||||
ends
|
||||
SYSCALL_METHOD_I40 = 1
|
||||
SYSCALL_METHOD_SYSENTER = 2
|
||||
SYSCALL_METHOD_SYSCALL = 3
|
||||
|
||||
macro _clear_ op
|
||||
{ mov ecx, op/4
|
||||
{
|
||||
mov ecx, op/4
|
||||
xor eax, eax
|
||||
cld
|
||||
rep stosd
|
||||
@ -98,30 +118,41 @@ proc fs_execute
|
||||
filename_size rd 1
|
||||
cmdline_size rd 1
|
||||
path_string rd 1
|
||||
pedescr rd 1
|
||||
endl
|
||||
|
||||
mov [flags], edx
|
||||
mov [cmdline], ecx
|
||||
mov [path_string], ebx
|
||||
mov [filename_size], eax
|
||||
mov esi, -ERROR_FILE_NOT_FOUND
|
||||
mov edi, -ERROR_FILE_NOT_FOUND
|
||||
test eax, eax
|
||||
jz .err_file
|
||||
stdcall load_file, ebx
|
||||
test eax, eax
|
||||
jz .err_file
|
||||
|
||||
stdcall load_file_maybe_pe, [path_string]
|
||||
mov [pedescr], esi
|
||||
mov [file_base], eax
|
||||
mov [file_size], ebx
|
||||
|
||||
test esi, esi
|
||||
jnz .file_ok
|
||||
|
||||
mov edi, eax
|
||||
cmp eax, -0x1000
|
||||
ja .err_file
|
||||
|
||||
lea ebx, [hdr_cmdline]
|
||||
call test_app_header ; fill our app header data locals with values from header of given program (if its correct)
|
||||
mov esi, -TASKMAN_ERROR_NOT_A_EXECUTABLE
|
||||
mov edi, -TASKMAN_ERROR_NOT_A_EXECUTABLE
|
||||
test eax, eax
|
||||
jz .err_hdr
|
||||
|
||||
.file_ok:
|
||||
call lock_application_table
|
||||
call alloc_thread_slot ; create a slot for new thread
|
||||
mov esi, -TASKMAN_ERROR_TOO_MANY_PROCESSES
|
||||
mov edi, -TASKMAN_ERROR_TOO_MANY_PROCESSES
|
||||
test eax, eax
|
||||
jz .err_0
|
||||
|
||||
@ -162,8 +193,15 @@ proc fs_execute
|
||||
add [hdr_emem], ebx
|
||||
@@:
|
||||
mov [cmdline_size], eax
|
||||
xor eax, eax
|
||||
cmp [pedescr], eax
|
||||
jz @f
|
||||
mov [hdr_eip], eax
|
||||
mov [hdr_esp], eax
|
||||
mov [hdr_emem], eax
|
||||
@@:
|
||||
stdcall create_process, [hdr_emem] ; create a new process
|
||||
mov esi, -TASKMAN_ERROR_OUT_OF_MEMORY
|
||||
mov edi, -TASKMAN_ERROR_OUT_OF_MEMORY
|
||||
test eax, eax
|
||||
jz .err_hdr
|
||||
|
||||
@ -203,12 +241,17 @@ proc fs_execute
|
||||
ret
|
||||
|
||||
.err_0:
|
||||
mov esi, [pedescr]
|
||||
test esi, esi
|
||||
jz @f
|
||||
call dereference_pe
|
||||
@@:
|
||||
call unlock_application_table
|
||||
.err_hdr:
|
||||
stdcall kernel_free, [file_base]
|
||||
.err_file:
|
||||
stdcall kernel_free, [path_string]
|
||||
mov eax, esi
|
||||
mov eax, edi
|
||||
ret
|
||||
endp
|
||||
|
||||
@ -330,13 +373,18 @@ proc create_process stdcall, app_size:dword
|
||||
jz .fail
|
||||
mov [process], eax
|
||||
|
||||
lea edi, [eax+PROC.heap_lock]
|
||||
mov ecx, (PROC.ht_free-PROC.heap_lock)/4
|
||||
lea edi, [eax+PROC.heap_base]
|
||||
|
||||
list_init eax
|
||||
add eax, PROC.thr_list
|
||||
list_init eax
|
||||
add eax, PROC.smap_list - PROC.thr_list
|
||||
list_init eax
|
||||
|
||||
lea ecx, [eax+PROC.heap_lock-PROC.smap_list]
|
||||
call mutex_init
|
||||
|
||||
mov ecx, (PROC.ht_free-PROC.heap_base)/4
|
||||
xor eax, eax
|
||||
cld
|
||||
rep stosd
|
||||
@ -370,6 +418,8 @@ proc create_process stdcall, app_size:dword
|
||||
|
||||
lea edx, [edi-4096]
|
||||
mov esi, [app_tabs]
|
||||
test esi, esi
|
||||
jz .no_page_dirs
|
||||
|
||||
.alloc_page_dir:
|
||||
call alloc_page
|
||||
@ -388,6 +438,7 @@ proc create_process stdcall, app_size:dword
|
||||
dec esi
|
||||
jnz .alloc_page_dir
|
||||
|
||||
.no_page_dirs:
|
||||
stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
|
||||
mov eax, [process]
|
||||
|
||||
@ -397,7 +448,7 @@ proc create_process stdcall, app_size:dword
|
||||
ret
|
||||
.fail:
|
||||
mov ecx, [process]
|
||||
jcxz @F
|
||||
jecxz @F
|
||||
|
||||
call destroy_process
|
||||
@@:
|
||||
@ -419,8 +470,6 @@ proc destroy_page_table stdcall, pg_tab:dword
|
||||
mov eax, [esi]
|
||||
test eax, 1
|
||||
jz .next
|
||||
test eax, 2
|
||||
jz .next
|
||||
test eax, 1 shl 9
|
||||
jnz .next ;skip shared pages
|
||||
call free_page
|
||||
@ -446,8 +495,16 @@ align 4
|
||||
mov esi, ecx
|
||||
list_del esi
|
||||
|
||||
mov esi, [esi+PROC.dlls_list_ptr]
|
||||
call destroy_all_hdlls
|
||||
lea ebx, [esi+PROC.smap_list]
|
||||
mov edi, [esi+PROC.smap_list+SMAP.fd]
|
||||
.smap_list_destroy:
|
||||
cmp edi, ebx
|
||||
jz .smap_list_done
|
||||
push [edi+SMAP.fd]
|
||||
stdcall destroy_smap, [esp+4]
|
||||
pop edi
|
||||
jmp .smap_list_destroy
|
||||
.smap_list_done:
|
||||
|
||||
mov esi, [esp]
|
||||
add esi, PROC.pdt_0
|
||||
@ -532,6 +589,7 @@ proc read_process_memory
|
||||
r_count dd ?
|
||||
offset dd ?
|
||||
tmp_r_cnt dd ?
|
||||
mapped_size dd ?
|
||||
endl
|
||||
|
||||
mov [slot], eax
|
||||
@ -541,6 +599,8 @@ proc read_process_memory
|
||||
mov [offset], esi
|
||||
|
||||
pushad
|
||||
mov ecx, proc_mem_mutex
|
||||
call mutex_lock
|
||||
.read_mem:
|
||||
mov edx, [offset]
|
||||
mov ebx, [tmp_r_cnt]
|
||||
@ -560,13 +620,14 @@ proc read_process_memory
|
||||
|
||||
push ecx
|
||||
stdcall map_memEx, [proc_mem_map], \
|
||||
[slot], ebx, ecx, PG_READ
|
||||
[slot], ebx, ecx, PG_READ, [proc_mem_tab]
|
||||
mov [mapped_size], eax
|
||||
pop ecx
|
||||
|
||||
mov esi, [offset]
|
||||
and esi, 0xfff
|
||||
sub eax, esi
|
||||
jbe .ret
|
||||
jbe .ret_unmap
|
||||
cmp ecx, eax
|
||||
jbe @f
|
||||
mov ecx, eax
|
||||
@ -574,17 +635,26 @@ proc read_process_memory
|
||||
@@:
|
||||
add esi, [proc_mem_map]
|
||||
mov edi, [buff]
|
||||
mov edx, ecx
|
||||
push ecx
|
||||
rep movsb
|
||||
add [r_count], edx
|
||||
stdcall unmap_memEx, [proc_mem_map], \
|
||||
[slot], ebx, [mapped_size], [proc_mem_tab]
|
||||
pop ecx
|
||||
add [r_count], ecx
|
||||
|
||||
add [offset], edx
|
||||
sub [tmp_r_cnt], edx
|
||||
add [offset], ecx
|
||||
sub [tmp_r_cnt], ecx
|
||||
jnz .read_mem
|
||||
.ret:
|
||||
mov ecx, proc_mem_mutex
|
||||
call mutex_unlock
|
||||
popad
|
||||
mov eax, [r_count]
|
||||
ret
|
||||
.ret_unmap:
|
||||
stdcall unmap_memEx, [proc_mem_map], \
|
||||
[slot], ebx, [mapped_size], [proc_mem_tab]
|
||||
jmp .ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
@ -603,6 +673,7 @@ proc write_process_memory
|
||||
w_count dd ?
|
||||
offset dd ?
|
||||
tmp_w_cnt dd ?
|
||||
mapped_size dd ?
|
||||
endl
|
||||
|
||||
mov [slot], eax
|
||||
@ -612,7 +683,9 @@ proc write_process_memory
|
||||
mov [offset], esi
|
||||
|
||||
pushad
|
||||
.read_mem:
|
||||
mov ecx, proc_mem_mutex
|
||||
call mutex_lock
|
||||
.write_mem:
|
||||
mov edx, [offset]
|
||||
mov ebx, [tmp_w_cnt]
|
||||
|
||||
@ -630,13 +703,14 @@ proc write_process_memory
|
||||
mov ebx, [offset]
|
||||
push ecx
|
||||
stdcall map_memEx, [proc_mem_map], \
|
||||
[slot], ebx, ecx, PG_SWR
|
||||
[slot], ebx, ecx, PG_SWR, [proc_mem_tab]
|
||||
mov [mapped_size], eax
|
||||
pop ecx
|
||||
|
||||
mov edi, [offset]
|
||||
and edi, 0xfff
|
||||
sub eax, edi
|
||||
jbe .ret
|
||||
jbe .ret_unmap
|
||||
cmp ecx, eax
|
||||
jbe @f
|
||||
mov ecx, eax
|
||||
@ -644,17 +718,25 @@ proc write_process_memory
|
||||
@@:
|
||||
add edi, [proc_mem_map]
|
||||
mov esi, [buff]
|
||||
mov edx, ecx
|
||||
push ecx
|
||||
rep movsb
|
||||
stdcall unmap_memEx, [proc_mem_map], \
|
||||
[slot], ebx, [mapped_size], [proc_mem_tab]
|
||||
pop ecx
|
||||
|
||||
add [w_count], edx
|
||||
add [offset], edx
|
||||
sub [tmp_w_cnt], edx
|
||||
jnz .read_mem
|
||||
add [w_count], ecx
|
||||
add [offset], ecx
|
||||
sub [tmp_w_cnt], ecx
|
||||
jnz .write_mem
|
||||
.ret:
|
||||
mov ecx, proc_mem_mutex
|
||||
call mutex_unlock
|
||||
popad
|
||||
mov eax, [w_count]
|
||||
ret
|
||||
.ret_unmap:
|
||||
stdcall unmap_memEx, [proc_mem_map], [slot], ebx, [mapped_size], [proc_mem_tab]
|
||||
jmp .ret
|
||||
endp
|
||||
|
||||
;ebx = 1 - kernel thread
|
||||
@ -799,6 +881,76 @@ common_app_entry:
|
||||
jz .exit
|
||||
; APPDATA.exec_params have first thread only,
|
||||
; so second and next threads don't get here (they jump to .exit)
|
||||
cmp [ebp+APP_HDR.pedescr], 0
|
||||
jz .init_legacy_app
|
||||
; init PE application
|
||||
mov eax, [current_process]
|
||||
mov [eax+PROC.mem_used], 0xF000 ; leave first 64K as unallocatable
|
||||
call init_heap
|
||||
mov eax, [current_process]
|
||||
mov [eax+PROC.mem_used], 0
|
||||
stdcall map_pe_usermode, [ebp+APP_HDR.pedescr],\
|
||||
[ebp+APP_HDR.img_base], [ebp+APP_HDR.img_size]
|
||||
cmp eax, -0x1000
|
||||
ja .failed
|
||||
push eax
|
||||
stdcall load_file_maybe_pe, pe_loader_usermode
|
||||
test esi, esi
|
||||
jz .pe_loader_notfound
|
||||
mov edx, [esi+PEDESCR.entry]
|
||||
mov [esp+4+20h], edx
|
||||
stdcall map_pe_usermode, esi, eax, ebx
|
||||
cmp eax, -0x1000
|
||||
ja .pe_loader_failed
|
||||
add [esp+4+20h], eax
|
||||
push eax
|
||||
mov eax, [ebp+APP_HDR.filename_size]
|
||||
add eax, [ebp+APP_HDR.cmdline_size]
|
||||
add eax, sizeof.kernel_init_data + 2
|
||||
stdcall user_alloc, eax
|
||||
test eax, eax
|
||||
jz .failed
|
||||
mov ebx, eax
|
||||
mov dword [eax+kernel_init_data.version], 1 + (0 shl 16) ; version, flags
|
||||
mov [eax+kernel_init_data.syscall_method], SYSCALL_METHOD_I40
|
||||
lea edi, [eax+sizeof.kernel_init_data]
|
||||
mov [eax+kernel_init_data.exe_path], edi
|
||||
mov esi, [ebp+APP_HDR.path_string]
|
||||
mov ecx, [ebp+APP_HDR.filename_size]
|
||||
rep movsb
|
||||
mov byte [edi], 0
|
||||
inc edi
|
||||
mov [eax+kernel_init_data.command_line], edi
|
||||
lea esi, [ebp+sizeof.APP_HDR]
|
||||
mov ecx, [ebp+APP_HDR.cmdline_size]
|
||||
rep movsb
|
||||
mov byte [edi], 0
|
||||
mov ecx, [ebp+APP_HDR.pedescr]
|
||||
mov ecx, [ecx+PEDESCR.stacksize]
|
||||
mov [eax+kernel_init_data.stack_size], ecx
|
||||
stdcall user_alloc, ecx
|
||||
test eax, eax
|
||||
jz .failed
|
||||
mov [ebx+kernel_init_data.stack_base], eax
|
||||
add eax, [ebx+kernel_init_data.stack_size]
|
||||
sub eax, 16
|
||||
pop dword [eax+4]
|
||||
pop [ebx+kernel_init_data.exe_base]
|
||||
mov dword [eax+8], 1 ; DLL_PROCESS_ATTACH
|
||||
mov dword [eax+12], ebx
|
||||
mov [esp+2Ch], eax
|
||||
jmp .common_tls
|
||||
.pe_loader_notfound:
|
||||
cmp eax, -0x1000
|
||||
ja .pe_loader_failed
|
||||
stdcall kernel_free, eax
|
||||
.pe_loader_failed:
|
||||
dbgstr 'Failed to load kolibri.dll'
|
||||
.failed:
|
||||
stdcall kernel_free, [ebp+APP_HDR.path_string]
|
||||
jmp sys_end
|
||||
.init_legacy_app:
|
||||
; init MENUETxx application
|
||||
stdcall map_process_image, [ebp+APP_HDR._emem],\
|
||||
[ebp+APP_HDR.img_base], [ebp+APP_HDR.img_size]
|
||||
mov esi, [ebp+APP_HDR.path_string]
|
||||
@ -846,8 +998,9 @@ common_app_entry:
|
||||
mov byte [edi], 0
|
||||
.check_tls_header:
|
||||
cmp word [6], '02'
|
||||
jne .try_load_dll ;.cleanup
|
||||
jne .try_load_dll ;.common
|
||||
call init_heap
|
||||
.common_tls:
|
||||
stdcall user_alloc, 4096
|
||||
mov edx, [current_slot]
|
||||
mov [edx+APPDATA.tls_base], eax
|
||||
@ -862,7 +1015,7 @@ common_app_entry:
|
||||
; Test app header version
|
||||
mov ecx, dword[ebp+APP_HDR.img_base]
|
||||
cmp dword[ecx+8], 2
|
||||
jne .cleanup
|
||||
jne .common
|
||||
;if APP_HEADER.version = 2 => load lib/dll.obj & change eip to APP_STARTUP_THUNK
|
||||
DEBUGF 1, 'K : App header version 2\n'
|
||||
stdcall load_library, dll_lib_path, 0
|
||||
@ -877,19 +1030,21 @@ common_app_entry:
|
||||
call fs_execute_from_sysdir_param
|
||||
; Terminate process (TODO: Need jump to .cleanup after sys_end ?)
|
||||
call sys_end
|
||||
|
||||
|
||||
@@:
|
||||
; Find APP_STARTUP_THUNK in DLL.OBJ
|
||||
sub eax, 4
|
||||
mov eax, [eax]
|
||||
|
||||
|
||||
;.change_eip:
|
||||
mov ecx, [current_slot]
|
||||
mov ecx, [ecx+APPDATA.pl0_stack]
|
||||
mov [ecx+REG_EIP], eax
|
||||
|
||||
; } End patch by Coldy, For DLL autoload
|
||||
.cleanup:
|
||||
mov fs, dx
|
||||
|
||||
.common:
|
||||
stdcall free_kernel_space, [ebp+APP_HDR.img_base]
|
||||
stdcall kernel_free, ebp
|
||||
mov ebx, [current_slot]
|
||||
|
@ -181,23 +181,25 @@ dev_data_path db '/RD/1/DRIVERS/DEVICES.DAT',0
|
||||
dll_lib_path db '/RD/1/LIB/DLL.OBJ',0
|
||||
dll_error_msg db '"DLL.OBJ not found!\nTerminate application!" -dE',0
|
||||
; } End patch by Coldy, For DLL autoload
|
||||
pe_loader_usermode db '/rd/1/lib/kolibri.dll',0
|
||||
|
||||
align 4
|
||||
|
||||
shmem_list:
|
||||
.bk dd shmem_list
|
||||
.fd dd shmem_list
|
||||
|
||||
dll_list:
|
||||
.bk dd dll_list
|
||||
.fd dd dll_list
|
||||
pe_list:
|
||||
.bk dd pe_list
|
||||
.fd dd pe_list
|
||||
|
||||
pcidev_list:
|
||||
.bk dd pcidev_list
|
||||
.fd dd pcidev_list
|
||||
|
||||
MAX_DEFAULT_DLL_ADDR = 0x80000000
|
||||
MIN_DEFAULT_DLL_ADDR = 0x70000000
|
||||
dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
|
||||
shared_locked_list:
|
||||
dd shared_locked_list
|
||||
dd shared_locked_list
|
||||
|
||||
; supported videomodes
|
||||
|
||||
@ -399,6 +401,12 @@ os_stack_seg dd ?
|
||||
srv.fd dd ?
|
||||
srv.bk dd ?
|
||||
|
||||
shmem_list_mutex MUTEX
|
||||
pe_list_mutex MUTEX
|
||||
shared_locked_mutex MUTEX
|
||||
proc_mem_mutex MUTEX
|
||||
ipc_mutex MUTEX
|
||||
|
||||
LFBAddress dd ?
|
||||
|
||||
PUTPIXEL dd ?
|
||||
@ -432,6 +440,7 @@ proc_mem_pdir dd ?
|
||||
proc_mem_tab dd ?
|
||||
|
||||
tmp_task_ptab dd ?
|
||||
zero_page_tab dd ?
|
||||
|
||||
default_io_map dd ?
|
||||
|
||||
|
@ -3660,6 +3660,67 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* edx = размер загруженного файла или 0
|
||||
Примечания:
|
||||
* функция загружает и, при необходимости, распаковывает файл (kunpack)
|
||||
======================================================================
|
||||
=========== Функция 68, подфункция 29 - загрузить PE-файл ============
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 68 - номер функции
|
||||
* ebx = 29 - номер подфункции
|
||||
* ecx = указатель на строку с путём к файлу,
|
||||
правила формирования строки указаны в описании функции 70.
|
||||
Возвращаемое значение:
|
||||
* eax > 0xFFFFF000 - произошла ошибка, -eax = код ошибки
|
||||
* eax <= 0xFFFFF000 - адрес загруженного файла
|
||||
Примечания:
|
||||
* функция предназначена только для системного загрузчика внутри
|
||||
kolibri.dll; загруженный файл ещё не готов к работе, ему требуется
|
||||
донастройка. Вместо неё используйте
|
||||
функцию dlopen() из kolibri.dll.
|
||||
======================================================================
|
||||
=========== Функция 68, подфункция 30 - выгрузить PE-файл ============
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 68 - номер функции
|
||||
* ebx = 30 - номер подфункции
|
||||
* ecx = адрес загруженного PE-файла
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно
|
||||
* eax = -1 - адрес не соответствует никакому загруженному файлу
|
||||
Примечания:
|
||||
* функция предназначена только для системного загрузчика внутри
|
||||
kolibri.dll. Вместо неё используйте функцию dlclose()
|
||||
из kolibri.dll.
|
||||
======================================================================
|
||||
==== Функция 68, подфункция 31 - изменить права доступа к памяти =====
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 68 - номер функции
|
||||
* ebx = 31 - номер подфункции
|
||||
* ecx = новые права доступа: ноль или более из следующих бит:
|
||||
* PROT_READ = 1 - разрешить чтение
|
||||
* PROT_WRITE = 2 - разрешить запись
|
||||
* PROT_EXEC = 4 - разрешить исполнение
|
||||
* edx = начальный адрес участка памяти
|
||||
* esi = размер участка памяти в байтах
|
||||
Возвращаемое значение:
|
||||
* eax = -1 - ошибка
|
||||
* иначе eax = старые права доступа
|
||||
Примечания:
|
||||
* Функция изменяет права целым страницам (4096 байт). Функция
|
||||
меняет права доступа у всех страниц, пересекающихся с запрошенным
|
||||
участком.
|
||||
* Функция считает ошибкой передачу участка памяти от функции 68.22.
|
||||
* Если часть переданного участка памяти корректна, а часть - нет,
|
||||
то функция возвращает ошибку, но не гарантируется, изменились ли
|
||||
права доступа у корректной части.
|
||||
* Если не было ошибки, то функция возвращает старые права доступа
|
||||
у первой из запрошенных страниц.
|
||||
* Текущая реализация не поддерживает разрешения исполнения отдельно
|
||||
от чтения. Поэтому бит PROT_EXEC игнорируется на входе и копирует
|
||||
разрешение на чтение на выходе.
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_SYS_MISC (68)
|
||||
ebx - SSF_MPROTECT (31)
|
||||
|
||||
======================================================================
|
||||
======================== Функция 69 - отладка. =======================
|
||||
|
@ -3645,6 +3645,68 @@ Remarks:
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_SYS_MISC (68)
|
||||
ebx - SSF_MEM_ALLOC_RING (29)
|
||||
======================================================================
|
||||
============ Function 68, subfunction 30 - load PE-file ==============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 68 - function number
|
||||
* ebx = 30 - subfunction number
|
||||
* ecx = pointer to the string with path to file,
|
||||
rules of path forming can be found in function 70 description.
|
||||
Returned value:
|
||||
* eax > 0xFFFFF000 - error, -eax = error code
|
||||
* eax <= 0xFFFFF000 - pointer to the loaded file
|
||||
Remarks:
|
||||
* This function is to be called only by system loader from
|
||||
kolibri.dll; the file loaded is not ready yet, it requires further
|
||||
configuration. Use dlopen() from kolibri.dll instead of this
|
||||
function.
|
||||
======================================================================
|
||||
=========== Function 68, subfunction 31 - unload PE-file =============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 68 - function number
|
||||
* ebx = 31 - subfunction number
|
||||
* ecx = pointer to the loaded file
|
||||
Returned value:
|
||||
* eax = 0 - success
|
||||
* eax = -1 - provided address does not correspond to any loaded file
|
||||
Remarks:
|
||||
* This function is to be called only by system loader from
|
||||
kolibri.dll. Use dlclose() from kolibri.dll instead of this
|
||||
function.
|
||||
======================================================================
|
||||
===== Function 68, subfunction 32 - modify memory access rights ======
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 68 - function number
|
||||
* ebx = 32 - subfunction number
|
||||
* ecx = new access rights: zero or more of the following bits:
|
||||
* PROT_READ = 1 - allow reading
|
||||
* PROT_WRITE = 2 - allow writing
|
||||
* PROT_EXEC = 4 - allow execution
|
||||
* edx = pointer to begin of memory region
|
||||
* esi = size of memory region in bytes
|
||||
Returned value:
|
||||
* eax = -1 - error
|
||||
* else eax = old access rights
|
||||
Remarks:
|
||||
* The function modifies access rights to whole pages (4096 bytes).
|
||||
* The function modifies access rights to all the pages intersecting
|
||||
provided memory region.
|
||||
* It is considered an error if a memory region returned by function
|
||||
68.22 is passed to this function.
|
||||
* If any part of the passed memory region is incorrect, then the
|
||||
function returns an error. However it is not guaranteed that
|
||||
access rights of the correct part have been changed.
|
||||
* If there was no error, the function returns old access rights of
|
||||
the first provided page.
|
||||
* Current implementation does not support execution access rights
|
||||
without reading rights. Therefore bit PROT_EXEC is ignored on
|
||||
entering the function, and becomes a copy of PROT_READ at exit.
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_SYS_MISC (68)
|
||||
ebx - SSF_MPROTECT (32)
|
||||
|
||||
======================================================================
|
||||
====================== Function 69 - debugging. ======================
|
||||
|
@ -322,6 +322,17 @@ high_code:
|
||||
mov ecx, application_table_mutex
|
||||
call mutex_init
|
||||
|
||||
mov ecx, shmem_list_mutex
|
||||
call mutex_init
|
||||
mov ecx, pe_list_mutex
|
||||
call mutex_init
|
||||
mov ecx, shared_locked_mutex
|
||||
call mutex_init
|
||||
mov ecx, proc_mem_mutex
|
||||
call mutex_init
|
||||
mov ecx, ipc_mutex
|
||||
call mutex_init
|
||||
|
||||
mov ecx, ide_mutex
|
||||
call mutex_init
|
||||
mov ecx, ide_channel1_mutex
|
||||
@ -513,6 +524,9 @@ high_code:
|
||||
add eax, ebx
|
||||
mov [ipc_ptab], eax
|
||||
|
||||
add eax, ebx
|
||||
mov [zero_page_tab], eax
|
||||
|
||||
stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl \
|
||||
(unpack.lc+unpack.lp)))*4
|
||||
|
||||
@ -2879,40 +2893,39 @@ align 4
|
||||
mov [bgrlockpid], eax
|
||||
cmp [img_background], static_background_data
|
||||
jz .nomem
|
||||
stdcall user_alloc, [mem_BACKGROUND]
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_lock
|
||||
stdcall user_alloc_nolock, [mem_BACKGROUND]
|
||||
mov [esp+32], eax
|
||||
test eax, eax
|
||||
jz .nomem
|
||||
jz .nomem_unlock
|
||||
mov ebx, eax
|
||||
shr ebx, 12
|
||||
or dword [page_tabs+(ebx-1)*4], MEM_BLOCK_DONT_FREE
|
||||
mov esi, [img_background]
|
||||
shr esi, 12
|
||||
mov ecx, [mem_BACKGROUND]
|
||||
add ecx, 0xFFF
|
||||
shr ecx, 12
|
||||
;--------------------------------------
|
||||
align 4
|
||||
.z:
|
||||
mov eax, [page_tabs+ebx*4]
|
||||
test al, 1
|
||||
jz @f
|
||||
call free_page
|
||||
;--------------------------------------
|
||||
align 4
|
||||
@@:
|
||||
mov eax, [page_tabs+esi*4]
|
||||
or al, PG_UWR
|
||||
or eax, PG_UWR+PG_SHARED
|
||||
mov [page_tabs+ebx*4], eax
|
||||
mov eax, ebx
|
||||
shl eax, 12
|
||||
invlpg [eax]
|
||||
inc ebx
|
||||
inc esi
|
||||
loop .z
|
||||
dec ecx
|
||||
jnz .z
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
ret
|
||||
;--------------------------------------
|
||||
align 4
|
||||
.nomem_unlock:
|
||||
mov ecx, [current_process]
|
||||
add ecx, PROC.heap_lock
|
||||
call mutex_unlock
|
||||
.nomem:
|
||||
and [bgrlockpid], 0
|
||||
mov [bgrlock], 0
|
||||
@ -2926,30 +2939,7 @@ nosb6:
|
||||
mov eax, [current_slot_idx]
|
||||
cmp [bgrlockpid], eax
|
||||
jnz .err
|
||||
mov eax, ecx
|
||||
mov ebx, ecx
|
||||
shr eax, 12
|
||||
mov ecx, [page_tabs+(eax-1)*4]
|
||||
test cl, MEM_BLOCK_USED or MEM_BLOCK_DONT_FREE
|
||||
jz .err
|
||||
jnp .err
|
||||
push eax
|
||||
shr ecx, 12
|
||||
dec ecx
|
||||
;--------------------------------------
|
||||
align 4
|
||||
@@:
|
||||
and dword [page_tabs+eax*4], 0
|
||||
mov edx, eax
|
||||
shl edx, 12
|
||||
push eax
|
||||
invlpg [edx]
|
||||
pop eax
|
||||
inc eax
|
||||
loop @b
|
||||
pop eax
|
||||
and dword [page_tabs+(eax-1)*4], not MEM_BLOCK_DONT_FREE
|
||||
stdcall user_free, ebx
|
||||
stdcall user_free, ecx
|
||||
mov [esp+32], eax
|
||||
and [bgrlockpid], 0
|
||||
mov [bgrlock], 0
|
||||
@ -4925,6 +4915,14 @@ if defined debug_com_base
|
||||
pop ax dx
|
||||
end if
|
||||
|
||||
if 0
|
||||
push eax edx
|
||||
mov al, bl
|
||||
mov dx, 0x402
|
||||
out dx, al
|
||||
pop edx eax
|
||||
end if
|
||||
|
||||
mov [msg_board_data+ecx], bl
|
||||
cmp byte [debug_direct_print], 1
|
||||
jnz .end
|
||||
|
@ -15,6 +15,7 @@ include "core/fpu.inc" ; all fpu/sse support
|
||||
include "core/memory.inc"
|
||||
include "core/mtrr.inc"
|
||||
include "core/heap.inc"
|
||||
include "core/peuser.inc"
|
||||
include "core/malloc.inc" ; small kernel heap
|
||||
include "core/taskman.inc"
|
||||
include "core/dll.inc"
|
||||
|
Loading…
Reference in New Issue
Block a user