1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
|
; SCCSID = @(#)file.asm 1.2 85/07/23
; SCCSID = @(#)file.asm 1.2 85/07/23
TITLE FILE - Pathname related system calls
NAME FILE
;
; Pathname related system calls. These will be passed direct text of the
; pathname from the user. They will need to be passed through the macro
; expander prior to being sent through the low-level stuff. I/O specs are
; defined in DISPATCH. The system calls are:
;
; $Open written
; $Creat written
; $ChMod written
; $Unlink written
; $Rename written
; $CreateTempFile written
; $CreateNewFile written
; $Extended_Open written DOS 4.00
; GetIOParms written DOS 4.00
;
; Revision history:
;
; Created: MZ 4 April 1983
; A000 version 4.00 Jan. 1988
.xlist
;
; get the appropriate segment definitions
;
include dosseg.asm
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGroup,CS:DOSGroup
.xcref
include dossym.inc
include devsym.inc
include fastopen.inc
include EA.inc ;AN000;
include version.inc
.cref
.list
.sall
EXTRN DOS_OPEN:NEAR,DOS_CREATE:NEAR,DOS_Create_New:NEAR
IF NOT IBMCOPYRIGHT
extrn Set_EXT_mode:near
ENDIF
I_need WFP_Start,WORD ; pointer to beginning of expansion
I_Need ThisCDS,DWORD ; pointer to curdir in use
I_need ThisSft,DWORD ; SFT pointer for DOS_Open
I_need pJFN,DWORD ; temporary spot for pointer to JFN
I_need JFN,WORD ; word JFN for process
I_need SFN,WORD ; word SFN for process
I_Need OpenBuf,128 ; buffer for filename
I_Need RenBuf,128 ; buffer for filename in rename
I_need Sattrib,BYTE ; byte attribute to search for
I_need Ren_WFP,WORD ; pointer to real path
I_need cMeta,BYTE
I_need EXTERR,WORD ; extended error code
I_need EXTERR_LOCUS,BYTE ; Extended Error Locus
i_need JShare,DWORD ; share jump table
I_need fSharing,BYTE ; TRUE => via ServerDOSCall
I_need FastOpenTable,BYTE
I_need CPSWFLAG,BYTE ;AN000;FT. cpsw falg
I_need EXTOPEN_FLAG,WORD ;AN000;FT. extended file open flag
I_need EXTOPEN_ON,BYTE ;AN000;FT. extended open flag
I_need EXTOPEN_IO_MODE,WORD ;AN000;FT. IO mode
I_need XA_from,BYTE ;AN000;;FT. for get/set XA
I_need SAVE_ES,WORD ;AN000;;FT. for get/set XA
I_need SAVE_DI,WORD ;AN000;;FT. for get/set XA
I_need SAVE_DS,WORD ;AN000;;FT. for get/set XA
I_need SAVE_SI,WORD ;AN000;;FT. for get/set XA
I_need SAVE_DX,WORD ;AN000;;FT. for get/set XA
I_need SAVE_BX,WORD ;AN000;;FT. for get/set XA
I_need SAVE_CX,WORD ;AN000;;FT. for get/set XA
I_need NO_FILTER_DPATH,DWORD ;AN000;; pointer to original path of dest
I_need Temp_Var,WORD ;AN000;;
I_need DOS34_FLAG,WORD ;AN000;;
I_need Temp_Var2,WORD ;AN000;;
if debug
I_need BugLev,WORD
I_need BugTyp,WORD
include bugtyp.asm
endif
BREAK <$Open - open a file from a path string>
;
; $Open - given a path name in DS:DX and an open mode in AL, access the file
; and return a handle
; Inputs: DS:DX - pointer to asciz name
; AL - open mode
; Outputs: Carry Set - AX has error code for invalid open
; Carry Clear - AX has per process handle number
; Registers modified: most
Procedure $Open,NEAR
ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
fmt TypSysCall,LevLog,<"Open\n">
fmt TypSysCall,LevArgs,<" Mode = $x file = '$S'\n">,<AX,DS,DX>
XOR AH,AH
Entry $Open2 ;AN000;
mov ch,attr_hidden+attr_system+attr_directory
call SetAttrib
MOV CX,OFFSET DOSGroup:DOS_Open ; address of routine to call
SaveReg <AX> ; Save mode on stack
IF DBCS ;AN000;
MOV [Temp_Var],0 ;AN000;KK. set variable with 0
ENDIF ;AN000;
AccessFile:
;
; Grab a free SFT.
;
IF DBCS ;AN000;
TEST [Temp_Var],8 ;AN000;;KK. volume id bit set ;AN000;
JZ novol ;AN000;;KK. no ;AN000;
OR [DOS34_FLAG],DBCS_VOLID ;AN000;;KK. set bit for transpath ;AN000;
novol: ;AN000;
ENDIF ;AN000;
EnterCrit critSFT
invoke SFNFree ; get a free sfn
LeaveCrit critSFT
JC OpenFailJ ; oops, no free sft's
MOV SFN,BX ; save the SFN for later
fmt TypAccess,LevSFN,<"AccessFile setting SFN to $x\n">,<BX>
MOV WORD PTR [ThisSFT],DI ; save the SF offset
MOV WORD PTR [ThisSFT+2],ES ; save the SF segment
;
; Find a free area in the user's JFN table.
;
invoke JFNFree ; get a free jfn
JNC SaveJFN
OpenFailJ:
JMP OpenFail ; there were free JFNs... try SFN
SaveJFN:
MOV WORD PTR [pJFN],DI ; save the jfn offset
MOV WORD PTR [pJFN+2],ES ; save the jfn segment
MOV [JFN],BX ; save the jfn itself
;
; We have been given an JFN. We lock it down to prevent other tasks from
; reusing the same JFN.
;
MOV BX,SFN
MOV ES:[DI],BL ; assign the JFN
MOV SI,DX ; get name in appropriate place
MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer
SaveReg <CX> ; save routine to call
invoke TransPath ; convert the path
RestoreReg <BX> ; restore routine to call
LDS SI,ThisSFT
ASSUME DS:NOTHING
JC OpenCleanJ ; no error, go and open file
CMP cMeta,-1
JZ SetSearch
MOV AL,error_file_not_found ; no meta chars allowed
OpenCleanJ:
JMP OpenClean
SetSearch:
RestoreReg <AX> ; Mode (Open), Attributes (Create)
;
; We need to get the new inheritance bits.
;
xor cx,cx
CMP BX,OFFSET DOSGroup:DOS_OPEN
JNZ DoOper
TEST AL,sharing_no_inherit ; look for no inher
JZ DoOper
AND AL,07Fh ; mask off inherit bit
MOV CX,sf_no_inherit
DoOper:
MOV [SI].sf_mode,0 ; initialize mode field to 0
MOV [SI.SF_mft],0 ; clean out sharing info
;
;------------------------------------------------------------HKN 8/7/88
; Check if this is an extended open. If so you must set the
; modes in sf_mode. Call Set_EXT_mode to do all this. See
; Set_EXT_mode in creat.asm
;
IF NOT IBMCOPYRIGHT
push es ; set up es:di to point to SFT
push di
push ds
pop es
push si
pop di
call Set_EXT_mode
pop di
pop es
ENDIF
;-----------------------------------------------------------------------
Context DS
SaveReg <CX>
CALL BX ; blam!
RestoreReg <CX>
LDS SI,ThisSFT
ASSUME DS:NOTHING
JC OpenE2 ;AN000;FT. chek extended open hooks first
;
; The SFT was successfully opened. Remove busy mark.
;
OpenOK:
ASSUME DS:NOTHING
; MOV AL,[SI].sf_attr_hi ;AN000;FT. save file type for EXEC
; MOV BYTE PTR [Temp_Var2],AL ;AN000;FT.
MOV [SI].sf_ref_count,1
OR [SI].sf_flags,CX ; set no inherit bit if necessary
;
; If the open mode is 70, we scan the system for other SFT's with the same
; contents. If we find one, then we can 'collapse' thissft onto the already
; opened one. Otherwise we use this new one. We compare uid/pid/mode/mft
;
; Since this is only relevant on sharer systems, we stick this code into the
; sharer.
;
MOV AX,JFN
if installed
Call JShare + 12 * 4
else
Call ShCol
endif
fmt TypAccess,LevSFN,<"AccessFile setting SFN to -1\n">
MOV SFN,-1 ; clear out sfn pointer
fmt TypSysCall,LevLog,<"Open/CreateXX: return $x\n">,<AX>
transfer Sys_Ret_OK ; bye with no errors
;Extended Open hooks check
OpenE2: ;AN000;;EO.
CMP AX,error_invalid_parameter ;AN000;;EO. IFS extended open ?
JNZ OpenE ;AN000;;EO. no.
JMP OpenCritLeave ;AN000;;EO. keep handle
;Extended Open hooks check
;
; AL has error code. Stack has argument to dos_open/dos_create.
;
OpenClean:
fmt TypSysCall,LevLog,<"Return value from transpath $x\n">,<AX>
RestoreReg <bx> ; clean off stack
OpenE:
MOV [SI.SF_Ref_Count],0 ; release SFT
LDS SI,pJFN
MOV BYTE PTR [SI],0FFh ; free the SFN...
JMP SHORT OpenCritLeave
OpenFail:
STI
RestoreReg <CX> ; Clean stack
OpenCritLeave:
MOV SFN,-1 ; remove mark.
fmt TypSysCall,LevLog,<"Open/CreateXX: error $x\n">,<AX>
;; File Tagging DOS 4.00
CMP CS:[EXTERR],error_Code_Page_Mismatched ;AN000;;FT. code page mismatch
JNZ NORERR ;AN000;;FT. no
transfer From_GetSet ;AN000;;FT. yes
NORERR: ;AN000;
;; File Tagging DOS 4.00
transfer Sys_Ret_Err ; no free, return error
EndProc $Open
BREAK <$Creat - create a brand-new file>
;
; $Creat - create the directory entry specified in DS:DX and give it the
; initial attributes contained in CX
; Inputs: DS:DX - ASCIZ path name
; CX - initial attributes
; Outputs: Carry set - AX has error code
; Carry reset - AX has handle
; Registers modified: all
Procedure $Creat,NEAR
ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
fmt TypSysCall,LevLog,<"Create\n">
fmt TypSysCall,LevArgs,<" Att = $x file = '$S'\n">,<CX,DS,DX>
IF DBCS ;AN000;
MOV [Temp_Var],CX ;AN000;KK. set variable with attribute ;AN000;
ENDIF ;AN000;
SaveReg <CX> ; Save attributes on stack
MOV CX,OFFSET DOSGroup:DOS_Create; routine to call
AccessSet:
mov SAttrib,attr_hidden+attr_system
JMP AccessFile ; use good ol' open
EndProc $Creat
BREAK <$CHMOD - change file attributes>
;
; Assembler usage:
; LDS DX, name
; MOV CX, attributes
; MOV AL,func (0=get, 1=set)
; INT 21h
; Error returns:
; AX = error_path_not_found
; AX = error_access_denied
;
procedure $CHMOD,NEAR
ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer
SaveReg <AX,CX> ; save function and attributes
MOV SI,DX ; get things in appropriate places
invoke TransPathSet ; get correct path
RestoreReg <CX,AX> ; and get function and attrs back
JC ChModErr ; errors get mapped to path not found
Context DS ; set up for later possible calls
CMP cMeta,-1
JNZ ChModErr
MOV [SAttrib],attr_hidden+attr_system+attr_directory
SUB AL,1 ; fast way to discriminate
JB ChModGet ; 0 -> go get value
JZ ChModSet ; 1 -> go set value
MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus
error error_invalid_function ; bad value
ChModGet:
invoke Get_File_Info ; suck out the ol' info
JC ChModE ; error codes are already set for ret
invoke Get_User_stack ; point to user saved vaiables
MOV [SI.User_CX],AX ; return the attributes
transfer Sys_Ret_OK ; say sayonara
ChModSet:
MOV AX,CX ; get attrs in position
invoke Set_File_Attribute ; go set
JC ChModE ; errors are set
transfer Sys_Ret_OK
ChModErr:
mov al,error_path_not_found
ChmodE:
Transfer SYS_RET_ERR
EndProc $ChMod
BREAK <$UNLINK - delete a file entry>
;
; Assembler usage:
; LDS DX, name
; IF VIA SERVER DOS CALL
; MOV CX,SEARCH_ATTRIB
; MOV AH, Unlink
; INT 21h
;
; Error returns:
; AX = error_file_not_found
; = error_access_denied
;
procedure $UNLINK,NEAR
ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
SaveReg <CX> ; Save possible CX input parm
MOV SI,DX ; Point at input string
MOV DI,OFFSET DOSGroup:OpenBuf ; temp spot for path
invoke TransPathSet ; go get normalized path
RestoreReg <CX>
JC ChModErr ; badly formed path
CMP cMeta,-1 ; meta chars?
JNZ NotFound
Context DS
mov ch,attr_hidden+attr_system ; unlink appropriate files
call SetAttrib
invoke DOS_Delete ; remove that file
JC UnlinkE ; error is there
transfer Sys_Ret_OK ; okey doksy
NotFound:
MOV AL,error_path_not_found
UnlinkE:
transfer Sys_Ret_Err ; bye
EndProc $UnLink
BREAK <$RENAME - move directory entries around>
;
; Assembler usage:
; LDS DX, source
; LES DI, dest
; IF VIA SERVER DOS CALL
; MOV CX,SEARCH_ATTRIB
; MOV AH, Rename
; INT 21h
;
; Error returns:
; AX = error_file_not_found
; = error_not_same_device
; = error_access_denied
procedure $RENAME,NEAR
ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
SaveReg <CX,DS,DX> ; save source and possible CX arg
PUSH ES
POP DS ; move dest to source
MOV SI,DI ; save for offsets
MOV DI,OFFSET DOSGroup:RenBuf
MOV WORD PTR [NO_FILTER_DPATH],SI ;AN000;;IFS. save them for IFS
MOV WORD PTR [NO_FILTER_DPATH+2],DS ;AN000;;IFS.
invoke TransPathSet ; munge the paths
PUSH WFP_Start ; get pointer
POP Ren_WFP ; stash it
RestoreReg <SI,DS,CX> ; get back source and possible CX arg
epjc2: JC ChModErr ; get old error
CMP cMeta,-1
JNZ NotFound
SaveReg <CX> ; Save possible CX arg
MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer
invoke TransPathSet ; wham
RestoreReg <CX>
JC EPJC2
Context DS
CMP cMeta,-1
JB NotFound
PUSH WORD PTR [THISCDS] ;AN000;;MS.save thiscds
PUSH WORD PTR [THISCDS+2] ;AN000;;MS.
MOV DI,OFFSET DOSGROUP:OpenBuf ;AN000;;MS.
PUSH SS ;AN000;;MS.
POP ES ;AN000;;MS.es:di-> source
XOR AL,AL ;AN000;;MS.scan all CDS
rnloop: ;AN000;
invoke GetCDSFromDrv ;AN000;;MS.
JC dorn ;AN000;;MS. end of CDS
invoke StrCmp ;AN000;;MS. current dir ?
JZ rnerr ;AN000;;MS. yes
INC AL ;AN000;;MS. next
JMP rnloop ;AN000;;MS.
rnerr: ;AN000;
ADD SP,4 ;AN000;;MS. pop thiscds
error error_current_directory ;AN000;;MS.
dorn: ;AN000;
POP WORD PTR SS:[THISCDS+2] ;AN000;;MS.
POP WORD PTR SS:[THISCDS] ;AN000;;MS.
Context DS
mov ch,attr_directory+attr_hidden+attr_system; rename appropriate files
call SetAttrib
invoke DOS_Rename ; do the deed
JC UnlinkE ; errors
transfer Sys_Ret_OK
EndProc $Rename
Break <$CreateNewFile - Create a new directory entry>
;
; CreateNew - Create a new directory entry. Return a file handle if there
; was no previous directory entry, and fail if a directory entry with
; the same name existed previously.
;
; Inputs: DS:DX point to an ASCIZ file name
; CX contains default file attributes
; Outputs: Carry Clear:
; AX has file handle opened for read/write
; Carry Set:
; AX has error code
; Registers modified: All
Procedure $CreateNewFile,NEAR
ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
fmt TypSysCall,LevLog,<"CreateNew\n">
fmt TypSysCall,LevArgs,<" Att = $x file = '$S'\n">,<CX,DS,DX>
IF DBCS ;AN000;
MOV [Temp_Var],CX ;AN000;KK. set variable with attribute
ENDIF ;AN000;
SaveReg <CX> ; Save attributes on stack
MOV CX,OFFSET DOSGroup:DOS_Create_New ; routine to call
JMP AccessSet ; use good ol' open
EndProc $CreateNewFile
Break <HexToAsciz - convert a number to hex and store it in memory>
;
; HexToAsciz - used to convert register into a hex number.
;
; Inputs: AX contains the number
; ES:DI point to destination
; Outputs: ES:DI updated
; Registers modified: DI,CX
Procedure HexToAsciz,NEAR
mov cx,4 ; 4 digits in AX
GetDigit:
SaveReg <CX> ; preserve count
mov cl,4
ROL AX,CL ; move leftmost nibble into rightmost
SaveReg <AX> ; preserve remainder of digits
AND AL,0Fh ; grab low nibble
ADD AL,'0' ; turn into digit
CMP AL,'9' ; bigger than 9
JBE DoStore ; no, stash it
ADD AL,'A'-'0'-10 ; convert into uppercase letter
DoStore:
STOSB ; drop in the character
RestoreReg <AX,CX> ; regain the number and count
loop GetDigit ; while there's more digits, go do 'em
return
EndProc HexToAsciz
Break <$CreateTempFile - create a unique name>
;
; $CreateTemp - given a directory, create a unique name in that directory.
; Method used is to get the current time, convert to a name and attempt
; a create new. Repeat until create new succeeds.
;
; Inputs: DS:DX point to a null terminated directory name.
; CX contains default attributes
; Outputs: Unique name is appended to DS:DX directory.
; AX has handle
; Registers modified: all
Procedure $CreateTempFile,NEAR
ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
fmt TypSysCall,LevLog,<"CreateTmp\n">
fmt TypSysCall,LevArgs,<" Att = $x dir = '$S'\n">,<CX,DS,DX>
PUBLIC FILE001S,FILE001E
FILE001S:
LocalVar EndPtr,DWORD
LocalVar FilPtr,DWORD
LocalVar Attr,WORD
FILE001E:
Enter
TEST CX,NOT attr_changeable
JZ OKatts ; Ok if no non-changeable bits set
;
; We need this "hook" here to detect these cases (like user sets one both of
; vol_id and dir bits) because of the structure of the or $CreateNewFile loop
; below. The code loops on error_access_denied, but if one of the non
; changeable attributes is specified, the loop COULD be infinite or WILL be
; infinite because CreateNewFile will fail with access_denied always. Thus we
; need to detect these cases before getting to the loop.
;
MOV AX,error_access_denied
JMP SHORT SETTMPERR
OKatts:
MOV attr,CX ; save attribute
MOV FilPtrL,DX ; pointer to file
MOV FilPtrH,DS
MOV EndPtrH,DS ; seg pointer to end of dir
PUSH DS
POP ES ; destination for nul search
MOV DI,DX
MOV CX,DI
NEG CX ; number of bytes remaining in segment
IF DBCS ;AN000;
Kloop: ;AN000;; 2/13/KK
MOV AL, BYTE PTR ES:[DI] ;AN000;; 2/13/KK
INC DI ;AN000;; 2/13/KK
OR AL,AL ;AN000;; 2/13/KK
JZ GOTEND ;AN000;; 2/13/KK
invoke testkanj ;AN000;; 2/13/KK
jz Kloop ;AN000;; 2/13/KK
inc di ;AN000;; Skip over second kanji byte 2/13/KK
CMP BYTE PTR ES:[DI],0 ;AN000;; 2/13/KK
JZ STOREPTH ;AN000; When char before NUL is sec Kanji byte
;AN000; do not look for path char. 2/13/KK
jmp Kloop ;AN000; 2/13/KK
GOTEND: ;AN000; 2/13/KK
ELSE ;AN000;
OR CX,CX ;AN000;MS. cx=0 ? ds:dx on segment boundary
JNZ okok ;AN000;MS. no
MOV CX,-1 ;AN000;MS.
okok: ;AN000;
XOR AX,AX ;AN000;
REPNZ SCASB ;AN000;
ENDIF ;AN000;
DEC DI ; point back to the null
MOV AL,ES:[DI-1] ; Get char before the NUL
invoke PathChrCmp ; Is it a path separator?
JZ SETENDPTR ; Yes
STOREPTH:
MOV AL,'\'
STOSB ; Add a path separator (and INC DI)
SETENDPTR:
MOV EndPtrL,DI ; pointer to the tail
CreateLoop:
Context DS ; let ReadTime see variables
SaveReg <BP>
invoke ReadTime ; go get time
RestoreReg <BP>
;
; Time is in CX:DX. Go drop it into the string.
;
les di,EndPtr ; point to the string
mov ax,cx
call HexToAsciz ; store upper word
mov ax,dx
call HexToAsciz ; store lower word
xor al,al
STOSB ; nul terminate
LDS DX,FilPtr ; get name
ASSUME DS:NOTHING
MOV CX,Attr ; get attr
SaveReg <BP>
CALL $CreateNewFile ; try to create a new file
RestoreReg <BP>
JNC CreateDone ; failed, go try again
;
; The operation failed and the error has been mapped in AX. Grab the extended
; error and figure out what to do.
;
mov ax,ExtErr
cmp al,error_file_exists
jz CreateLoop ; file existed => try with new name
cmp al,error_access_denied
jz CreateLoop ; access denied (attr mismatch)
; CMP AL,error_file_exists ; certain errors cause failure
; JZ CreateLoop
; CMP AL,error_access_denied
; JNZ SETTMPERR ; Error out
; CMP [EXTERR],error_cannot_make ; See if it's REALLY an att mismatch
; JNZ CreateLoop ; It was, try again
; MOV AL,error_cannot_make ; Return this "extended" error
SETTMPERR:
STC
CreateDone:
Leave
JC CreateFail
transfer Sys_Ret_OK ; success!
CreateFail:
transfer Sys_Ret_Err
EndProc $CreateTempFile
Break <SetAttrib - set the search attrib>
;
; SetAttrib will set the search attribute (SAttrib) either to the normal
; (CH) or to the value in CL if the current system call is through
; serverdoscall.
;
; Inputs: fSharing == FALSE => set sattrib to CH
; fSharing == TRUE => set sattrib to CL
; Outputs: none
; Registers changed: CX
procedure SetAttrib,NEAR
assume ds:nothing,es:nothing
test fSharing,-1
jnz Set
mov cl,ch
Set:
mov SAttrib,cl
return
EndProc SetAttrib
Break <Extended_Open- Extended open the file>
; Input: AL= 0 reserved AH=6CH
; BX= mode
; CL= create attribute CH=search attribute (from server)
; DX= flag
; DS:SI = file name
; ES:DI = parm list
; DD SET EA list (-1) null
; DW n parameters
; DB type (TTTTTTLL)
; DW IOMODE
; Function: Extended Open
; Output: carry clear
; AX= handle
; CX=1 file opened
; 2 file created/opened
; 3 file replaced/opened
; carry set: AX has error code
;
procedure $Extended_Open,NEAR ;AN000;
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000;
MOV [XA_from],0 ;AN000;EO. init for set XA
MOV [EXTOPEN_FLAG],DX ;AN000;EO. save ext. open flag
MOV [EXTOPEN_IO_MODE],0 ;AN000;EO. initialize IO mode
TEST DX,reserved_bits_mask ;AN000;EO. reserved bits 0 ?
JNZ ext_inval2 ;AN000;EO. no
MOV AH,DL ;AN000;EO. make sure flag is right
CMP DL,0 ;AN000;EO. all fail ?
JZ ext_inval2 ;AN000;EO. yes, error
AND DL,exists_mask ;AN000;EO. get exists action byte
CMP DL,2 ;AN000;EO, > 02
JA ext_inval2 ;AN000;EO. yes ,error
AND AH,not_exists_mask ;AN000;EO. get no exists action byte
CMP AH,10H ;AN000;EO. > 10
JA ext_inval2 ;AN000;EO. yes error
; CMP DI,-1 ;AN000;EO. null parm list
; JZ no_parm ;AN000;EO. yes
; ;AN000;EO
; PUSH CX ;AN000;EO.
; ;AN000;EO.
; MOV CX,ES:[DI.EXT_NUM_OF_PARM];AN000;EO. get number of parms
; OR CX,CX ;AN000;EO. 0 pamrs ?
; JZ parmend ;AN000;EO. yes
; PUSH SI ;AN000;EO.
; PUSH DS ;AN000;EO.
; MOV SI,DI ;AN000;EO.
; ADD SI,size EXT_OPEN_PARM ;AN000;EO. position to 1st parm
; PUSH ES ;AN000;EO.
; POP DS ;AN000;EO. ds:si -> parm list
; CALL GetIOParms ;AN000;EO.
; POP DS ;AN000;EO.
; POP SI ;AN000;EO.
;parmend: ;AN000;EO
; POP CX ;AN000;EO. restore CX
;no_parm: ;AN000;EO.
MOV [SAVE_ES],ES ;AN000;EO. save API parms
MOV [SAVE_DI],DI ;AN000;EO.
PUSH [EXTOPEN_FLAG] ;AN000;EO.
POP [SAVE_DX] ;AN000;EO.
MOV [SAVE_CX],CX ;AN000;EO.
MOV [SAVE_BX],BX ;AN000;EO.
MOV [SAVE_DS],DS ;AN000;EO.
MOV [SAVE_SI],SI ;AN000;EO.
MOV DX,SI ;AN000;EO. ds:dx points to file name
MOV AX,BX ;AN000;EO. ax= mode
; TEST [EXTOPEN_FLAG],no_code_page_check ;AN000;EO. check no code page
; JNZ no_cdpg_chk ;AN000;;EO. no
JMP SHORT goopen2 ;AN000;;EO. do nromal
ext_inval2: ;AN000;;EO.
error error_Invalid_Function ;AN000;EO.. invalid function
ext_inval_parm: ;AN000;EO..
POP CX ;AN000;EO.. pop up satck
POP SI ;AN000;EO..
error error_Invalid_data ;AN000;EO.. invalid parms
error_return: ;AN000;EO.
ret ;AN000;EO.. return with error
;no_cdpg_chk: EO.
; MOV [CPSWFLAG],0 ;AN000;EO.. set CPSW flag off
goopen2: ;AN000;
TEST BX,int_24_error ;AN000;EO.. disable INT 24 error ?
JZ goopen ;AN000;EO.. no
OR [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;EO.. set bit to disable
goopen: ;AN000;
OR [EXTOPEN_ON],EXT_OPEN_ON ;AN000;EO.. set Extended Open active
AND [EXTOPEN_FLAG],0FFH ;AN000;EO.create new ?
CMP [EXTOPEN_FLAG],ext_exists_fail + ext_nexists_create ;AN000;FT.
JNZ chknext ;AN000;;EO. no
invoke $CreateNewFile ;AN000;;EO. yes
JC error_return ;AN000;;EO. error
CMP [EXTOPEN_ON],0 ;AN000;;EO. IFS does it
JZ ok_return2 ;AN000;;EO. yes
MOV [EXTOPEN_FLAG],action_created_opened ;AN000;EO. creted/opened
MOV [XA_from],By_Create ;AN000;;EO. for set xa
JMP setXAttr ;AN000;;EO. set XAs
ok_return2:
transfer SYS_RET_OK ;AN000;;EO.
chknext:
TEST [EXTOPEN_FLAG],ext_exists_open ;AN000;;EO. exists open
JNZ exist_open ;AN000;;EO. yes
invoke $Creat ;AN000;;EO. must be replace open
JC error_return ;AN000;;EO. return with error
CMP [EXTOPEN_ON],0 ;AN000;;EO. IFS does it
JZ ok_return2 ;AN000;;EO. yes
MOV [EXTOPEN_FLAG],action_created_opened ;AN000;EO. prsume create/open
MOV [XA_from],By_Create ;AN000;EO. for set xa
TEST [EXTOPEN_ON],ext_file_not_exists ;AN000;;EO. file not exists ?
JNZ setXAttr ;AN000;;EO. no
MOV [EXTOPEN_FLAG],action_replaced_opened ;AN000;;EO. replaced/opened
MOV [XA_from],0 ;AN000;EO. for set xa
JMP SHORT setXAttr ;AN000;;EO. set XAs
error_return2:
ret ;AN000;;EO. return with error
;AN000;
exist_open: ;AN000;
test fSharing,-1 ;AN000;;EO. server doscall?
jz noserver ;AN000;;EO. no
MOV CL,CH ;AN000;;EO. cl=search attribute
noserver:
invoke $Open2 ;AN000;;EO. do open
JNC ext_ok ;AN000;;EO.
CMP [EXTOPEN_ON],0 ;AN000;;EO. error and IFS call
JZ error_return2 ;AN000;;EO. return with error
local_extopen:
CMP AX,error_file_not_found ;AN000;;EO. file not found error
JNZ error_return2 ;AN000;;EO. no,
TEST [EXTOPEN_FLAG],ext_nexists_create;AN000;;EO. want to fail
JNZ do_creat ;AN000;;EO. yes
JMP extexit ;AN000;;EO. yes
do_creat:
MOV [XA_from],By_Create ;AN000;;EO. for set xa
MOV CX,[SAVE_CX] ;AN000;;EO. get ds:dx for file name
LDS SI,DWORD PTR [SAVE_SI] ;AN000;;EO. cx = attribute
MOV DX,SI ;AN000;;EO.
invoke $Creat ;AN000;;EO. do create
JC extexit ;AN000;;EO. error
MOV [EXTOPEN_FLAG],action_created_opened ;AN000;;EO. is created/opened
JMP SHORT setXAttr ;AN000;;EO. set XAs
ext_ok:
CMP [EXTOPEN_ON],0 ;AN000;;EO. IFS call ?
JZ ok_return ;AN000;;EO. yes
MOV [EXTOPEN_FLAG],action_opened ;AN000;;EO. opened
setXAttr:
; LES DI,DWORD PTR [SAVE_DI] ;AN000;EO.
PUSH AX ;AN000;;EO. save handle for final
; MOV BX,AX ;AN000;;EO. bx= handle
; MOV AX,04H ;AN000;;EO. set extended attr by handle
; PUSH DS ;AN000;;EO. save file name addr
; PUSH DX ;AN000;;EO.
; CMP DI,-1 ;AN000;;EO. null parm list
; JZ nosetea ;AN000;;EO. yes
; CMP WORD PTR ES:[DI],-1 ;AN000;;EO. null set list
; JZ nosetea ;AN000;;EO. yes
; LES DI,DWORD PTR ES:[DI] ;AN000;;EO. es:di -> set list
; invoke $File_times ;AN000;;EO.
;nosetea: ;AN000; EO
; POP DX ;AN000;;EO. restore file name addr
; POP DS ;AN000;;EO.
; JC extexit2 ;AN000;;EO.
invoke get_user_stack ;AN000;;EO.
MOV AX,[EXTOPEN_FLAG] ;AN000;;EO.
MOV [SI.USER_CX],AX ;AN000;;EO. set action code for cx
POP AX ;AN000;;EO.
MOV [SI.USER_AX],AX ;AN000;;EO. set handle for ax
ok_return: ;AN000;
transfer SYS_RET_OK ;AN000;;EO.
extexit2: ;AN000; ERROR RECOVERY
POP BX ;AN000;EO. close the handle
PUSH AX ;AN000;EO. save error code from set XA
CMP [EXTOPEN_FLAG],action_created_opened ;AN000;EO. from create
JNZ justopen ;AN000;EO.
LDS SI,DWORD PTR [SAVE_SI] ;AN000;EO. cx = attribute
LDS DX,DWORD PTR [SI] ;AN000;EO.
invoke $UNLINK ;AN000;EO. delete the file
JMP SHORT reserror ;AN000;EO.
justopen: ;AN000;
invoke $close ;AN000;EO. pretend never happend
reserror: ;AN000;
POP AX ;AN000;EO. retore error code from set XA
JMP SHORT extexit ;AN000;EO.
ext_file_unfound: ;AN000;
MOV AX,error_file_not_found ;AN000;EO.
JMP SHORT extexit ;AN000;EO.
ext_inval: ;AN000;
MOV AX,error_invalid_function;AN000;EO.
extexit:
transfer SYS_RET_ERR ;AN000;EO.
EndProc $Extended_Open ;AN000;
Break <GetIOParms - get IO parms form extended open parm list>
;
;
; Inputs: DS:SI -> IO parm list
; CX= number of parms
; Function: get IO parms from parm list
; Outputs: [EXT_IOMODE]= IO mode parm
;procedure GetIOParms,NEAR
; assume ds:nothing,es:nothing
;
; LODSB ; get parm type ;AN000;
; CMP AL,0*100B+10B ; have IOMODE ;AN000;
; JE SET_IOMODE ;AN000;
; AND AL,00000011B ; decode it ;AN000;
; JZ SKIP_ASCIIZ ;AN000;
; DEC AL ;AN000;
; JZ SKIP_LEN ;AN000;
;; DEC AL ;AN000;
; JZ SKIP_WORD ;AN000;
;SKIP_DWORD: ; copy DWORD parm ;AN000;
; LODSW ;AN000;
;SKIP_WORD: ; copy WORD parm ;AN000;
; LODSW ;AN000;
; JMP SHORT NEXT_PARM ;AN000;
;SET_IOMODE: ; copy IOMODE ;AN000;
; LODSW ;AN000;
; MOV [EXTOPEN_IO_MODE],AX ;AN000;
; JMP SHORT NEXT_PARM ;AN000;
;SKIP_LEN: ; copy LENGTH parm ;AN000;
; LODSW ;AN000;
; ADD SI,AX ;AN000;
; JMP SHORT NEXT_PARM ;AN000;
;SKIP_ASCIIZ: ; copy ASCIIZ parm ;AN000;
; LODSB ;AN000;
; OR AL,AL ;AN000;
; JNE SKIP_ASCIIZ ;AN000;
;NEXT_PARM: ;AN000;
; LOOP GetIOParms ;AN000;
; return ;AN000;
;EndProc GetIOParms ;AN000;
CODE ENDS
END
|