[Edit: Ooops, that question already been answered a few years ago on Stack Overflow]
I'd expect there to be some reference (either a file handle or an old-fashioned FCB) in the PSP, but there's nothing I can find.
Almost. While there is no file handle or FCB to the program file, as it is already closed before execution starts, DOS (starting with 3.0) stores the program name as ASCIZ within the environment memory block, right after all environment variables.
- Test for min DOS version 3.0
- Get the environment segment from offset 002Ch of the PSP
- Advance after the last environment variable
- marked by two consecutive null bytes
- There's a word with the number of strings following
- If at least 1, the program name follows
- Fetch the program name (a full ASCIZ path name)
- Open that file
- Do whatever you want to do :))
This works for .COM and .EXE programs - but only with DOS 3.0 and above.
In Assembly this may look a bit like:
MOV AH,3000h ; Get DOS version
JC LOWDOS ; Call failed -> DOS 1.x ?
CMP AL,3 ; At least DOS 3
JAE DOSOK ; Yes -> continue
LOWDOS: ; DOS version too low: terminate with exit code = 126
MOV AX,CS:[2Ch] ; Environment Segment
MOV ES,AX ; to DS
XOR DI,DI ; Point ES:DI at start of environment vars
MOV AX,DI ; Search for 0-bytes
CLD ; Upward
MOV CX,32767 ; Maximum size of an environment segment
;Loop skipping all environment variables
REPNE SCASB ; Skip a string
JCXZ NFND ; Searched max.length without finding a zero
CMP AL,BYTE ES:[DI] ; next byte as well Zero ?
JNE SKIPVAR ; No -> Skip next var
INC DI ; Skip over zero byte
CMP WORD ES:[DI],AX; String count not zero ?
JE NFND ; No -> Not Found
INC DI ; Skip string count
; Full Program Name at ES:DI
; Do whatever is to be done
; like opening it via 3Dh:
MOV DX,DI ; Filename in DS:DX
MOV AL,<openmode> ; Read/Write/etc...
MOV AH,3Dh ; Open File
; Open Error: terminate with exit code = openerror code
; Name Not Found: terminate with exit code = 127
; Read or write from/to the program file
; File Handle in AX
Rather easy, isn't it?