Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2816 clevermous 1
; Platform-specific procedures for Windows.
2
 
3
; Reallocate memory at pointer [start.buf] and size [start.allocated],
4
; new size is in eax.
5
realloc:
6
        push    eax
7
        stdcall [VirtualAlloc], 0, eax, MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE
8
        pop     ecx
9
        test    eax, eax
10
        jz      nomemory
11
        add     [start.free], ecx
12
        xchg    ecx, [start.allocated]
13
        sub     [start.free], ecx
14
        push    esi edi
15
        mov     edi, eax
16
        xchg    eax, [start.buf]
17
        shr     ecx, 2
18
        jz      .nothing
19
        mov     esi, eax
20
        rep     movsd
21
        call    free_eax
22
.nothing:
23
        pop     edi esi
24
        ret
25
 
26
; Read the next portion of input data to [start.buf].
27
read:
28
        push    eax     ; reserve space for *lpNumberOfBytesRead
29
        mov     ecx, esp
30
        mov     eax, [start.buf]
31
        add     eax, [start.allocated]
32
        sub     eax, [start.free]
33
        stdcall [ReadFile], [start.in], eax, [start.free], ecx, 0
34
        test    eax, eax
35
        jz      @f
36
.nothing:
37
        pop     eax
38
        ret
39
@@:
40
; ERROR_BROKEN_PIPE and ERROR_MORE_DATA are normal codes when dealing with pipes
41
        call    [GetLastError]
42
        cmp     eax, ERROR_BROKEN_PIPE
43
        jz      .nothing
44
        cmp     eax, ERROR_MORE_DATA
45
        jz      .nothing
46
        pop     eax
47
        jmp     readerr
48
 
49
; Write output data: eax=pointer, edi=size.
50
write:
51
        push    eax
52
        mov     ecx, esp
53
        stdcall [WriteFile], [start.out], eax, edi, ecx, 0
54
        test    eax, eax
55
        pop     eax
56
        jz      writeerr
57
        cmp     eax, edi
58
        jnz     writeerr
59
        ret
60
 
61
; Parse command line, open input and output files.
62
get_params:
63
; 1. Get the command line split to argv[] array.
64
        call    [GetCommandLineW]
65
        push    eax     ; reserve space for *pNumArgs
66
        stdcall [CommandLineToArgvW], eax, esp
67
        pop     ebx     ; ebx = argc, eax = argv
68
        push    eax     ; save argument for [LocalFree]
69
; 2. Prepare for scanning, skipping argv[0].
70
        cmp     ebx, 1
71
        jbe     .noargs
72
        dec     ebx
73
        lea     esi, [eax+4]    ; skip argv[0]
74
        xor     edi, edi        ; no args parsed yet
75
; 3. Parse loop.
76
.parse:
77
; 3a. Get the next argument.
78
        lodsd
79
; 3b. Check whether it is a known option.
80
        cmp     dword [eax], '-' + 'e' * 65536
81
        jnz     @f
82
        cmp     word [eax+4], 0
83
        jnz     @f
84
; 3c. If it is, modify flags and continue the loop.
85
        mov     [start.flags], 1        ; '-e' is given
86
        jmp     .nextarg
87
@@:
88
; 3d. Otherwise, it is a name of input or output file.
89
; edi keeps the count of names encountered before;
90
; edi = 0 means this is input file, edi = 1 - output file,
91
; otherwise this is third arg, which is an error
92
        cmp     edi, 1
93
        ja      .toomanyargs
94
; 3e. Some parameters of CreateFileW differ for input and output. Setup them.
95
        mov     ecx, GENERIC_WRITE
96
        mov     edx, CREATE_ALWAYS
97
        jz      @f
98
        add     ecx, ecx        ; GENERIC_READ
99
        inc     edx             ; OPEN_EXISTING
100
@@:
101
; 3f. Open/create the file, save the handle.
102
        stdcall [CreateFileW], eax, ecx, FILE_SHARE_READ+FILE_SHARE_DELETE, 0, edx, FILE_ATTRIBUTE_NORMAL, 0
103
        cmp     eax, INVALID_HANDLE_VALUE
104
        jz      .fileerr
105
        mov     [start.in+edi*4], eax
106
        inc     edi
107
.nextarg:
108
        dec     ebx
109
        jnz     .parse
110
.noargs:
111
; 4. End of command line reached. If input and/or output was not given, use defaults.
112
        test    edi, edi
113
        jnz     .hasinput
114
        stdcall [GetStdHandle], STD_INPUT_HANDLE
115
        mov     [start.in], eax
116
.hasinput:
117
        cmp     edi, 1
118
        ja      .hasoutput
119
        stdcall [GetStdHandle], STD_OUTPUT_HANDLE
120
        mov     [start.out], eax
121
.hasoutput:
122
; 5. Free memory allocated in step 1 and return.
123
        call    [LocalFree]
124
        ret
125
.toomanyargs:
126
        call    [LocalFree]
127
        jmp     information
128
.fileerr:
129
        call    [LocalFree]
130
        test    edi, edi
131
        jz      in_openerr
132
        jmp     out_openerr
133
 
134
; Exit, return code is in al.
135
exit:
136
        movzx   eax, al
137
        push    eax     ; save return code for [ExitProcess]
138
        mov     eax, [start.buf]
139
        test    eax, eax
140
        jz      @f
141
        call    free_eax
142
@@:
143
        stdcall [CloseHandle], [start.in]
144
        stdcall [CloseHandle], [start.out]
145
        call    [ExitProcess]
146
 
147
; Output the message given in esi to stderr.
148
sayerr:
149
        stdcall [GetStdHandle], STD_ERROR_HANDLE
150
        push    eax
151
        mov     ecx, esp
152
        movzx   edx, byte [esi-1]
153
        stdcall [WriteFile], eax, esi, edx, ecx, 0
154
        pop     ecx
155
        ret
156
 
157
; Helper procedure for realloc and exit.
158
free_eax:
159
        stdcall [VirtualFree], eax, 0, MEM_RELEASE
160
        ret
161
 
162
; Get environment variable esi (ebx-relative pointer) to the buffer,
163
; expanding it if needed.
164
get_environment_variable:
165
        lea     eax, [edi+ebx]
166
        lea     ecx, [esi+ebx]
167
        stdcall [GetEnvironmentVariableA], ecx, eax, [start.free]
168
; GetEnvironmentVariable returns one of following values:
169
; * if all is ok: number of characters copied to the buffer,
170
;       not including terminating zero
171
; * if buffer size is too small: number of characters required in the buffer,
172
;       including terminating zero
173
; * if environment variable not found: zero
174
; We treat the last case the same as first one.
175
        cmp     eax, [start.free]
176
        jae     .resize
177
        inc     eax     ; include terminating zero
178
        add     edi, eax
179
        sub     [start.free], eax
180
        mov     byte [edi+ebx-1], 0     ; force zero-terminated or empty string
181
        ret
182
.resize:
183
; esi can be inside the buffer or outside the buffer;
184
; we must not correct it in the first case,
185
; but advance relative to new value of ebx in the second one.
186
        mov     ecx, esi
187
        cmp     esi, [start.allocated]
188
        jb      @f
189
        add     esi, ebx
190
@@:
191
        stdcall alloc_in_buf, eax
192
        cmp     esi, ecx
193
        jz      get_environment_variable
194
        sub     esi, ebx
195
        jmp     get_environment_variable
196
 
197
; Test whether a file with name [.testname] exists.
198
; Returns eax<0 if not, nonzero otherwise.
199
test_file_exists:
200
        mov     eax, [start.testname]
201
        add     eax, ebx
202
        stdcall [GetFileAttributesA], eax
203
        inc     eax
204
        ret
205
 
206
; Imports
207
align 4
208
data import
209
library kernel32,'kernel32.dll',shell32,'shell32.dll'
210
import kernel32, \
211
        GetLastError, 'GetLastError', \
212
        ExitProcess, 'ExitProcess', \
213
        VirtualAlloc, 'VirtualAlloc', \
214
        VirtualFree, 'VirtualFree', \
215
        LocalFree, 'LocalFree', \
216
        GetStdHandle, 'GetStdHandle', \
217
        CreateFileW, 'CreateFileW', \
218
        GetFileAttributesA, 'GetFileAttributesA', \
219
        ReadFile, 'ReadFile', \
220
        WriteFile, 'WriteFile', \
221
        CloseHandle, 'CloseHandle', \
222
        GetCommandLineW, 'GetCommandLineW', \
223
        GetEnvironmentVariableA, 'GetEnvironmentVariableA'
224
import shell32, CommandLineToArgvW, 'CommandLineToArgvW'
225
end data