| >Look in the VMS sources, at routine EXE$FORCEX. This routine queues a user-mode
>AST to a target process, with the AST's service-routine being SYS$EXIT.
>It should not be too difficult to extend this code to do what you wish.
I once did this (although I don't have the code right now...) it is very
easy, the $FORCEX code works just as it is.
The only snag is that the AST to be executed by the other process has to
be either in system space (maybe in a bit of nonpaged pool) or in its process
space. I wrote a profiler (we were too cheap to buy PCA :-) which required
the process being profiled to be linked with the AST code in a based cluster
at some large address like %X100000 . The AST did things like looking back
through the stack to get call frame information, if the current PC was not
in any known routine of the program. As far as I know, the presence of the
AST code doesn't affect the program in any way, although it does sometimes
reshuffle a few virtual addresses.
I may be able to post code if you need it.
= Giles =
|
| In the code that follows the <FF>, ASTADR is presumed to be the address of
the AST in the *other_guy's* process space. You can put it there by linking
the other process' image with a based cluster:
$ LINK blah,blah,sys$input/options
cluster=ast_code,%X100000,,ast_code.obj
Then use 100000 (hex) as the value of ASTADR.
= Giles =
.title QAST - que an AST to another process.
.library /SYS$LIBRARY:LIB.MLB/
$acbdef
$ipldef
$pcbdef
$prdef
$pridef
$ssdef
;
epid=4
prcnam=8
astadr=12
astprm=16
;
.PSECT KERNEL_QAST,con,exe,nowrt,long
;
; CALLING SEQUENCE:
; integer*4 epid,astprm,QAST
; character*12 prcnam ! or 0
; external ASTADR
; iret=QAST(epid,prcnam,%LOC(ASTADR),astprm)
;
; INPUT PARAMETERS:
; epid(ap) - address of pid (r/w)
; prcnam(ap) - address of process name (descr) or 0 if using pid
; astadr(ap) - address of ast within the process' space (***by ref***)
; astprm(ap) - ast parameter
;
; OUTPUT PARAMETERS:
; epid(ap) - pid of process for which exit was forced
; QAST - completion status
;
; COMPLETION CODES:
; ss$_normal - successful completion
; ss$_accvio - cant read arg list
;
.entry QAST,^M<R2,R3,R4,R5>
;
$cmkrnl_s -
routin=kernel_qast,-
arglst=(ap)
ret
;
.entry KERNEL_QAST,^m<r2,r3,r4,r5>
;
ifnord #4,astadr(ap),30$ ; other 2 checked by EXE$NAMPID
ifnord #4,astprm(ap),30$
movl g^SCH$GL_CURPCB,r4
jsb g^EXE$NAMPID ; name to PID
setipl #0
blbc r0,20$
pushl r1
jsb g^EXE$ALLOCIRP ; give us an IRP to make an ACB
blbc r0,20$
;
movb #3,acb$b_rmod(r2) ; build an ACB for user mode
movl (sp)+,acb$l_pid(r2)
movl @astadr(ap) ,acb$l_ast(r2)
movl @astprm(ap),acb$l_astprm(r2)
movl r2,r5
movzbl #pri$_resavl,r2
;
jsb g^SCH$QAST ; queue the ACB
;
movzwl #ss$_normal,r0
20$: ret
;
30$: movzwl #ss$_accvio,r0 ; error return
ret
;
.end
|
| Thanks. It's much simpler than I thought it would be.
Now, since I can't force everything on the system to be linked with
a fixed base code segment, I wonder if there is some scratch space
in the allocated IRP/ACB wherein I could put the CALL/RET and arglist
for the system service call I desire to have executed. Also, if
I put this stuff in the IRP, can the acmode of the AST stay 'user'?
Dave
|