Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  226.