summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/SHARE/GSHARE2.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/SHARE/GSHARE2.ASM')
-rw-r--r--v4.0/src/CMD/SHARE/GSHARE2.ASM2979
1 files changed, 2979 insertions, 0 deletions
diff --git a/v4.0/src/CMD/SHARE/GSHARE2.ASM b/v4.0/src/CMD/SHARE/GSHARE2.ASM
new file mode 100644
index 0000000..6341c5a
--- /dev/null
+++ b/v4.0/src/CMD/SHARE/GSHARE2.ASM
@@ -0,0 +1,2979 @@
1 Title Share_2
2; $SALUT (0,36,41,44)
3 include SHAREHDR.INC
4;
5; Label: "The DOS SHARE Utility"
6; "Version 4.00 (C) Copyright 1988 Microsoft"
7; "Licenced Material - Program Property of Microsoft"
8;
9;******************* END OF SPECIFICATIONS *************************************
10
11 NAME Sharer2
12
13 ; INCLUDE DOSSYM.INC
14 ; INCLUDE SYSMSG.INC
15 .xlist
16 .xcref
17 INCLUDE DOSSYM.INC
18 INCLUDE SYSMSG.INC
19 .cref
20 .list
21 page 80,132
22
23 MSG_UTILNAME <SHARE>
24
25ShareDataVersion = 1
26
27AsmVars <IBM, Installed>
28
29Installed = TRUE ; for installed version
30
31OFF Macro reg,val
32 IF installed
33 mov reg,OFFSET val
34 ELSE
35 mov si,OFFSET DOSGROUP:val
36 ENDIF
37 ENDM
38
39ERRNZ Macro x
40 IF x NE 0
41 %out ERRNZ failed
42 ENDIF
43 ENDM
44 ;---------------------------------------
45 ; if we are installed, then define the
46 ; base code segment of the sharer first
47 ;---------------------------------------
48; $SALUT (4,9,17,36)
49
50 IF Installed
51
52 Share SEGMENT BYTE PUBLIC 'SHARE'
53 Share ENDS
54
55 ENDIF
56
57 ;---------------------------------------
58 ; include the rest of the segment
59 ; definitions for normal msdos
60
61 ; segment ordering for MSDOS
62
63 ;---------------------------------------
64 include dosseg.asm
65
66 CONSTANTS SEGMENT
67
68 extrn DataVersion:BYTE ; version number of DOS data.
69 extrn JShare:BYTE ; location of DOS jump table.
70 extrn sftFCB:DWORD ; [SYSTEM] pointer to FCB cache table
71 extrn KeepCount:WORD ; [SYSTEM] LRU count for FCB cache
72 extrn CurrentPDB:WORD
73
74 CONSTANTS ENDS
75
76 DATA SEGMENT
77
78 extrn ThisSFT:DWORD ; pointer to SFT entry
79 extrn WFP_start:WORD ; pointer to name string
80 extrn User_ID:WORD
81 extrn Proc_ID:WORD
82 extrn SFT_addr:DWORD
83 extrn Arena_Head:WORD
84 extrn fshare:BYTE
85 extrn pJFN:DWORD
86 extrn JFN:WORD
87
88 IF DEBUG
89
90 extrn BugLev:WORD
91 extrn BugTyp:WORD
92 include bugtyp.asm
93
94 ENDIF
95
96
97 DATA ENDS
98
99 ;---------------------------------------
100 ; if we are not installed, then the
101 ; code here is just part of the normal
102 ; MSDOS code segment otherwise,
103 ; define our own code segment
104 ;---------------------------------------
105
106 .sall
107 IF NOT INSTALLED
108
109 CODE SEGMENT BYTE PUBLIC 'CODE'
110
111 ASSUME SS:DOSGROUP,CS:DOSGROUP
112
113 ELSE
114
115 Share SEGMENT BYTE PUBLIC 'SHARE'
116
117 ASSUME SS:DOSGROUP,CS:SHARE
118
119 ENDIF
120
121 Extrn FreLock:WORD,Serial:WORD
122 Extrn MFT_Enter:NEAR,MFTClose:NEAR,MFTClu:NEAR,MFTCloseP:NEAR
123 Extrn MFTCloN:NEAR
124 Extrn Set_Mult_Block:NEAR,Clr_Mult_Block:NEAR,Chk_Block:NEAR
125 Extrn MFT_Get:NEAR
126
127 include mft.inc
128
129; $SALUT (4,4,9,41)
130
131 BREAK <FNM - Find name in MFT>
132
133;******************* START OF SPECIFICATIONS ***********************************
134;
135; FNM - Find name in MFT
136;
137; FNM searches the MFT for a name record.
138;
139; ENTRY (DS:SI) = pointer to name string (.asciz)
140; (al) = 1 to create record if non exists
141; = 0 otherwise
142; EXIT 'C' clear if found or created
143; (DS:BX) = address of MFT name record
144; 'C' set if error
145; If not to create, item not found
146; (DS:SI) unchanged
147; If to create, am out of space
148; (ax) = error code
149; USES ALL
150;
151;******************* END OF SPECIFICATIONS *************************************
152
153 Procedure FNM,NEAR
154
155 push ds ; save string address
156 push si
157 xchg bh,al ; (bh) = create flag
158 or bh,bh ; if not creating
159 jz fnm01 ; skip sft test
160
161 ;---------------------------------------
162 ; run down through string counting
163 ; and summing
164 ;---------------------------------------
165
166fnm01: sub dx,dx ; (dx) = byte count
167 sub bl,bl ; (bl) = sum
168
169fnm1: lodsb ; (al) = next char
170 add bl,al
171 adc bl,0
172 inc dx
173 and al,al
174 jnz fnm1 ; terminate after null char
175
176 ;---------------------------------------
177 ; Info computed.
178 ; Start searching name list
179
180 ; (bh) = create flag
181 ; (bl) = sum byte
182 ; (dx) = byte count
183 ; (TOS+2:TOS) = name string address
184 ;---------------------------------------
185 push cs
186 pop ds
187
188 Off SI,mft
189
190fnm2: cmp [si].mft_flag,MFLG_FRE
191 jl fnm10 ; at end - name not found
192 jz fnm4 ; is free, just skip it
193 cmp bl,[si].mft_sum ; do sums compare?
194 jz fnm5 ; its a match - look further
195fnm4: add si,[si].mft_len ; not a match... skip it
196 JMP SHORT fnm2
197 ;---------------------------------------
198 ; name checksums match
199 ; - compare the actual strings
200 ;
201 ; (dx) = length
202 ; (ds:si = MFT address
203 ; (bh) = create flag
204 ; (bl) = sum byte
205 ; (dx) = byte count
206 ; (TOS+2:TOS) = name string address
207 ;---------------------------------------
208
209fnm5: mov cx,dx ; (cx) = length to match
210 pop di
211 pop es ; (ES:DI) = fba given name
212 push es
213 push di
214 push si ; save MFT offset
215 add si,mft_name ; (ds:si) = fwa string in record
216 repz cmpsb
217 pop si ; (ds:si) = fwa name record
218 jnz fnm4 ; not a match
219
220 ;---------------------------------------
221 ; Yes, we've found it. Return the info
222 ;
223 ; (TOS+2:TOS) = name string address
224 ;---------------------------------------
225
226 fmt TypShare,LevMFTSrch,<"FNM found name record at $x\n">,<si>
227 pop ax ; discard unneeded stack stuff
228 pop ax
229 mov bx,si ; (ds:bx) = fwa name record
230 clc
231
232 ret
233 ;---------------------------------------
234 ;**
235 ;** Its not in the list
236 ;** - lets find a free spot and put
237 ;** it there
238 ;
239 ; (bh) = create flag
240 ; (bl) = sum byte
241 ; (dx) = string length
242 ; (TOS+2:TOS) = ASCIZ string address
243 ; (ds) = SEG CODE
244 ;---------------------------------------
245fnm10:
246 and bh,bh
247 jnz fnm10$5 ; yes, insert it
248 pop si
249 pop ds ; no insert, its a "not found"
250 stc
251
252 fmt TypShare,LevMFTSrch,<"FNM failing\n">
253
254 mov ax,error_path_not_found
255
256 ret
257
258fnm10$5:
259 add dx,mft_name ; (dx) = minimum space needed
260
261 off SI,mft
262
263fnm11: cmp [si].mft_flag,MFLG_FRE
264
265 IF NOT DEBUG
266 jl fnm20 ; at END, am out of space
267 ELSE
268 jl fnm20j
269 ENDIF
270
271 jz fnm12 ; is a free record
272 add si,[si].mft_len ; skip name record
273 JMP SHORT fnm11
274
275 IF DEBUG
276fnm20j: jmp fnm20
277 ENDIF
278
279fnm12: mov ax,[si].mft_len ; Have free record, (ax) = total length
280 cmp ax,dx
281 jnc fnm13 ; big enough
282 add si,ax
283 JMP SHORT fnm11 ; not large enough - move on
284
285 ;---------------------------------------
286 ; OK, we have a record which is big
287 ; enough. If its large enough to hold
288 ; another name record of 6 characters
289 ; than we'll split the block, else
290 ; we'll just use the whole thing
291 ;
292 ; (ax) = size of free record
293 ; (dx) = size needed
294 ; (ds:si) = address of free record
295 ; (bl) = sum byte
296 ; (TOS+2:TOS) = name string address
297 ;---------------------------------------
298
299fnm13: sub ax,dx ; (ax) = total size of proposed fragment
300 cmp ax,mft_name+6
301 jc fnm14 ; not big enough to split
302 push bx ; save sum byte
303 mov bx,dx ; (bx) = offset to start of new name record
304 mov [bx][si].mft_flag,MFLG_FRE
305 mov [bx][si].mft_len,ax ; setup tail as free record
306 sub ax,ax ; don't extend this record
307 pop bx ; restore sum byte
308fnm14: add dx,ax ; (dx) = total length of this record
309 mov [si].mft_len,dx
310 mov [si].mft_sum,bl
311 mov [si].mft_flag,MFLG_NAM
312
313 fmt TypShare,LevMFTSrch,<"FNM creating record at $x\n">,<si>
314
315 push ds
316 pop es ; (es) = MFT segment for "stow"
317 sub ax,ax
318 mov di,si
319 add di,mft_lptr
320 stosw ; zero LCK pointer
321 ERRNZ mft_sptr-mft_lptr-2
322; add di,mft_sptr-mft_lptr-2
323 stosw ; zero SFT pointer
324 stosw ; zero SFT pointer
325 inc serial ; bump serial number
326 mov ax,serial
327 ERRNZ mft_serl-mft_sptr-4
328; ADD di,mft_serl-mft_sptr-4
329 stosw
330 ;---------------------------------------
331 ; We're all setup except for the name.
332 ; Note that we'll block copy the whole
333 ; name field, even though the name may
334 ; be shorter than that (we may have
335 ; declined to fragment this memory block)
336 ;
337 ; (dx) = total length of this record
338 ; (ds:si) = address of working record
339 ; (es) = (ds)
340 ; (TOS+2:TOS) = name string address
341 ;---------------------------------------
342 mov cx,dx
343 sub cx,mft_name ; compute total size of name area
344 ERRNZ mft_name-mft_serl-2
345; add di,mft_name-mft_serl-2 ; (ES:DI) = target address
346 mov ax,si ; save name record offset
347 pop si
348 pop ds
349 rep movsb
350 mov bx,ax ; (bx) = name record offset
351 push es
352 pop ds ; (DS:BX) = name record offset
353 clc
354
355 ret
356
357;**
358;** OUT OF FREE SPACE
359;**
360;** This is tough, folks. Lets trigger a garbage collection and see if
361;** there is enough room. If there is, we'll hop back and relook for a
362;** free hunk; if there isnt enough space, its error-city!
363;
364; WARNING: it is important that the garbage collector be told how big a
365; name record hole we're looking for... if the size given GCM
366; is too small we'll loop doing "no space; collect; no space;
367; ...)
368;
369; (dx) = total length of desired name record
370; (ds) = SEG CODE
371; (bl) = sum byte
372; (TOS+2:TOS) = name string address
373
374fnm20:
375 mov ax,dx ; (ax) = size wanted
376 sub dx,mft_name ; (dx) = string length for reentry at fnm10
377 push dx
378 push bx
379 call GCM ; garbage collect MFT
380 pop bx
381 pop dx
382
383 IF DEBUG
384 jnc fnm10j
385 ELSE
386 jnc fnm10 ; go back and find that space
387 ENDIF
388
389 ;---------------------------------------
390 ; no space, return w/error
391 ;---------------------------------------
392
393fnm50: pop ax
394 pop ax ; clean stack
395 mov ax,error_sharing_buffer_exceeded
396 stc
397
398 ret
399
400 IF DEBUG
401fnm10j: jmp fnm10
402 ENDIF
403
404 EndProc FNM
405
406 BREAK <GCM - Garbage Collect MFT>
407
408;******************* START OF SPECIFICATIONS ***********************************
409;
410; GCM - Garbage Collect MFT
411;
412; GCM runs down the MFT structure squeezing out the free space and
413; putting it into one free block at the end. This is a traditional heap
414; collection process. We must be sure to update the pointer in the
415; SFTs. This presumes no adjacent free blocks.
416;
417; ENTRY (ax) = space desired in last free block
418; (DS) + SEG CODE
419; EXIT 'C' clear if enough space in block
420; 'C' set if not enough space
421;
422;******************* END OF SPECIFICATIONS *************************************
423
424 Procedure GCM,NEAR
425
426 push ax ; save target
427 off si,mft ; (si) = from pointer
428 mov di,si ; (di) = to pointer
429
430 ;---------------------------------------
431 ; (DI) points to the beginning of
432 ; a free space block
433 ; (SI) points to the next block.
434 ;---------------------------------------
435
436gcm1: mov cx,[si].mft_len ; (cx) = size of whatever it is
437 cmp [si].mft_flag,MFLG_FRE
438 jl gcm10 ; END marker
439 jnz gcm2 ; have a name record
440
441 ;---------------------------------------
442 ; (SI) points to a free block.
443 ; We coalesce it by changing the size.
444 ;---------------------------------------
445 cmp si,di
446 jz gcm15 ; do NOT coalesce a block with itself
447 add [di].mft_len,cx ; coalesce
448gcm15:
449 add si,cx ; skip the empty one
450 JMP SHORT gcm1
451 ;---------------------------------------
452 ; (SI) points to a non-free,
453 ; non-last block.
454 ; (DI) points to the beginning of a
455 ; free block.
456 ;
457 ; We move the non-free block down over
458 ; the free block
459 ;---------------------------------------
460gcm2: cmp si,di
461 jnz gcm3 ; have to copy
462
463 ;---------------------------------------
464 ; SI = DI => we are at a boundary
465 ; between allocated blocks.
466 ; We do no copying.
467 ;---------------------------------------
468 add si,cx
469 mov di,si ; no emptys yet... no need to copy
470 JMP SHORT gcm1
471 ;---------------------------------------
472 ; CX is length of allocated block.
473 ; - Move it
474 ;---------------------------------------
475
476gcm3: mov bx,di ; (DS:BX) = new home for this record
477 mov ax,ds
478 mov es,ax
479 rep movsb
480 ;---------------------------------------
481 ; We've moved the record, now fix up
482 ; the pointers in the SFT chain
483 ;
484 ; (si) = address of next record
485 ; (di) = address of next free byte
486 ; (bx) = address of record in its new home
487 ; (TOS) = needed space
488 ;---------------------------------------
489 push di
490 push ds
491 lds di,[bx].mft_sptr ; (ds:di) = chain of SFT
492gcm4: or di,di
493 jz gcm5 ; no more SFT
494 mov [di].sf_mft,bx ; install new MFT position
495 lds di,[di].sf_chain ; link to next
496 JMP gcm4 ; fix next SFT
497
498gcm5: pop ds
499 pop di
500 ;---------------------------------------
501 ; (DI) points to beginning of
502 ; new free record (moved)
503 ; (SI) points to next record
504 ;
505 ; Make sure that the (DI) record
506 ; has correct format
507 ;---------------------------------------
508
509 mov [di].mft_flag,MFLG_FRE ; indicate free record
510 mov [di].mft_len,si ; calculate correct length
511 sub [di].mft_len,di
512 ;---------------------------------------
513 ; MFT now has correct record structure.
514 ; Go find more free blocks
515 ;---------------------------------------
516 JMP SHORT gcm1
517 ;---------------------------------------
518 ; We have scanned the entire table,
519 ; compacting all empty records together.
520 ;
521 ; (di) = first free byte in table
522 ; (si) = address of END record
523 ; (TOS) = size needed
524 ;
525 ; Be extra careful!!!
526 ;---------------------------------------
527gcm10: mov ax,si
528 sub ax,di ; (ax) = free space
529 pop bx ; (bx) = space wanted
530 sub ax,bx
531
532 ret
533
534 EndProc GCM
535
536 BREAK <RMN - Remove MFT Name record>
537
538;******************* START OF SPECIFICATIONS ***********************************
539;
540; RMN - Remove MFT Name record
541;
542; RMN removes a name record from the MFT list. The record is marked
543; free and all free space is coalesced.
544;
545; ENTRY (DS:BX) = FBA MFT name record
546; EXIT to INTERR if lock and SFT chains are not empty
547; USES ALL
548;
549;******************* END OF SPECIFICATIONS *************************************
550
551 Procedure RMN,NEAR
552
553 mov si,bx
554 mov ax,word ptr [si].mft_sptr
555 or ax,word ptr [si].mft_lptr
556 jnz RMNIER1 ; not clean - internal error
557 mov si,bx ; (ds:si) = fwa name record
558
559 mov [si].mft_flag,MFLG_FRE ; mark free
560
561 call mrg ; coalesce all free space
562
563 ret
564
565RMNIER1:push ax
566 off ax,rmnerr1
567
568RMNIER: call INTERR ; internal error
569
570rmnerr1 db "RMN: SFT LCK fields not 0", 13, 10, 0
571
572 EndProc RMN
573
574 Break <MRG - merge all free space>
575
576;******************* START OF SPECIFICATIONS ***********************************
577;
578; MRG - merge all free space
579;
580; MRG - walk through mft merging adjacent free space.
581;
582; Inputs: ds = CS
583; Outputs: none (all free space coalesced)
584; Registers Revised: none
585;
586;******************* END OF SPECIFICATIONS *************************************
587
588 Procedure MRG,near
589
590 assume ds:nothing,es:nothing
591
592 push si
593 push bx
594
595 off si,mft ; start at beginning
596mrg1: mov bx,[si].mft_len ; get length
597 cmp [si].mft_flag,MFLG_FRE ; is record free?
598 jl mrg9 ; done.
599 jz mrg2 ; yes, try to merge with next
600mrg15: add si,bx ; advance to next
601 jmp mrg1
602 ;---------------------------------------
603 ; (si) points to free record.
604 ; - See if next is free
605 ;---------------------------------------
606mrg2: cmp [bx][si].mft_flag,MFLG_FRE
607 jnz mrg15 ; not free, go scan again
608 mov bx,[bx][si].mft_len ; get length of next guy
609 add [si].mft_len,bx ; increase our length
610 jmp mrg1 ; and check again
611mrg9: pop bx
612 pop si
613
614 ret
615
616 EndProc MRG
617
618 BREAK <RSC - Remove SFT from SFT chain>
619
620;******************* START OF SPECIFICATIONS ***********************************
621;
622; RSC - Remove SFT from SFT chain
623;
624; RSC removes a given SFT from its chain. The caller must insure that
625; any locks have been cleared and that the SFT is indeed free. The
626; sf_mft field is zeroed to indicate that this SFT is no longer chained.
627;
628; NOTE - RSC does NOT remove the name record if this was the last SFT on
629; it. The caller must check for this and remove it, if
630; necessary.
631;
632; ENTRY (ES:DI) = SFT address
633; EXIT (DS:BX) = FBA name record for this SFT
634; 'Z' set if this is the last SFT
635; USES ALL
636;
637;******************* END OF SPECIFICATIONS *************************************
638
639 Procedure RSC,NEAR
640
641 push cs
642 pop ds
643
644 mov ax,es ; easy spot for compare
645 mov bx,es:[di].sf_mft
646 lea si,[bx].mft_sptr-sf_chain ; ds:[si].sf_chain point to prev link
647rsc1: or si,si
648 jz rscier
649 cmp word ptr [si].sf_chain,di
650 jnz rsc15
651 cmp word ptr [si].sf_chain+2,ax
652 jz rsc2
653rsc15: lds si,[si].sf_chain
654 jmp rsc1
655 ;---------------------------------------
656 ; (es:di) is sft
657 ; (ds:si) is prev sft link
658 ;---------------------------------------
659rsc2: mov ax,word ptr es:[di].sf_chain
660 mov word ptr ds:[si].sf_chain,ax
661 mov ax,word ptr es:[di].sf_chain+2
662 mov word ptr ds:[si].sf_chain+2,ax
663
664 push cs
665 pop ds
666 xor bx,bx
667 xchg bx,es:[di].sf_MFT ; (DS:bx) = MFT address
668 ; and 0 MFT pointer (show free)
669 cmp word ptr [bx].mft_sptr,0 ; set z flag if no more sft
670
671 ret
672
673rscier: push ax
674 off ax,rscerr
675
676 call interr
677
678rscerr db "RSC: SFT not in SFT list", 13, 10, 0
679
680 EndProc RSC
681
682 BREAK <SLE - Scan for Lock Entry>
683
684;******************* START OF SPECIFICATIONS ***********************************
685;
686; SLE - Scan for Lock Entry
687;
688; SLE scans a lock list looking for a lock range that overlaps the
689; caller-supplied range. SLE indicates:
690;
691; no overlap
692; partial overlay
693; 1-to-1 match
694;
695; ENTRY (AX:BX) = FBA of area
696; (CX:DX) = LBA of area
697; (DS:SI) = address of name record
698; (DI) = 0 to ignore locks by User_ID Proc_ID ThisSFT
699; = 1 to consider all locks
700; EXIT 'C' clear if no overlap
701; AX,BX,CX,DX preserved
702; 'C' set if overlap
703; (di) = address of pointer to found record
704; (i.e., DS:((di)) = address of lock record)
705; 'Z' set if 1-to-1 match
706; USES ALL but (ds), (es) (also see EXIT)
707;
708;******************* END OF SPECIFICATIONS *************************************
709
710 Procedure SLE,NEAR
711
712 push es
713 and di,di
714 pushf ; Z set to ignore own locks
715 lea di,[si].mft_lptr ; (ds:di) = addr of ptr to lock record
716 mov si,[di] ; (ds:si) = address of 1st lock record
717
718 ;---------------------------------------
719 ; check out next lock
720 ;
721 ; (ds:si) = address of next lock record
722 ; (ds:di) = address of pointer to next
723 ; lock record
724 ; (TOS) = flags (Z set to ignore
725 ; own locks)
726 ; (TOS+1) = Saved ES
727 ;---------------------------------------
728sle1: and si,si
729 jz sle9 ; list exhaused, ergo no overlap
730 popf ;
731 pushf
732 jnz sle2 ; am to check all locks
733
734 ;---------------------------------------
735 ; am to ignore own locks...
736 ; check the user and proc IDs on this one
737 ;---------------------------------------
738
739;dcl - this code used to compare the process id in the sft pointed to by the
740; lock. now we compare the lock process id to the current process id. this
741; allows a child process to lock an area and then do i/o with it. before,
742; the child could lock it, but then could not access it
743
744
745 mov bp,[si].rlr_pid ;dcl
746 cmp bp,Proc_id ;dcl
747 jnz sce1$5 ;dcl
748 les si,[si].rlr_sptr ; (si) = sft address ;dcl
749 mov bp,es:[si].sf_UID ;dcl
750 cmp bp,User_ID ;dcl
751 jnz sce1$5 ; doesn't belong to user ;dcl
752 mov bp,es ;dcl
753 cmp bp,WORD PTR ThisSFT+2
754 jnz sce1$5
755 cmp si,WORD PTR ThisSFT
756sce1$5: mov si,[di] ; (ds:si) = address of next lock record
757 jz sle3 ; owned by user - ignore
758
759sle2: mov bp,dx
760 sub bp,[si].rlr_fba ; compare proposed last to first of record
761 mov bp,cx
762 sbb bp,[si].rlr_fba+2
763 jc sle3 ; proposed is above current
764 mov bp,[si].rlr_lba
765 sub bp,bx ; compare proposed first to last of record
766 mov bp,[si].rlr_lba+2
767 sbb bp,ax
768 jnc sle5 ; we have a hit
769
770 ;---------------------------------------
771 ; This entry is harmless...
772 ; chain to the next one
773 ;---------------------------------------
774 ERRNZ rlr_next
775
776sle3: mov di,si ; save addr of pointer to next
777 mov si,[di]
778 JMP SHORT sle1
779 ;---------------------------------------
780 ; We have an overlap.
781 ; - See if its an exact match
782 ;
783 ; (ds:di) = address of pointer
784 ; (offset only) to the lock record
785 ; (ds:si) = address of lock record
786 ; (TOS) = flags ('Z' set if to ignore
787 ; own locks)
788 ; (TOS+1) = saved (es)
789 ;---------------------------------------
790
791sle5: xor ax,[si].rlr_fba+2 ; require a 4-word match
792 xor bx,[si].rlr_fba
793 xor cx,[si].rlr_lba+2
794 xor dx,[si].rlr_lba
795 or ax,bx
796 or ax,cx
797 or ax,dx ; 'Z' set if exact match
798 stc ; flag an overlap
799 mov ax,error_lock_violation
800sle9: pop bp ; discard flags (pushf)
801 pop es ; restore (es)
802
803 ;---------------------------------------
804 ; (ds:si) = address of lock record
805 ; for Chk_Block
806 ;---------------------------------------
807 ret
808
809 EndProc SLE
810
811 BREAK <OFL - obtain free lock-record>
812
813;******************* START OF SPECIFICATIONS ***********************************
814;
815; OFL - obtain free lock-record
816;
817; OFL returns a free lock-record, if one can be had.
818;
819; ENTRY (DS) = MFT Segment
820; EXIT 'C' clear if OK
821; (DI) = FBA lock record
822; 'C' set if no space
823; (ax) = error code
824; USES DI, FLAGS
825;
826;******************* END OF SPECIFICATIONS *************************************
827
828 Procedure OFL,NEAR
829
830 mov di,Frelock
831 and di,di
832
833; $if nz ; if something there
834 JZ $$IF1
835
836 push [di].rlr_next
837 pop Frelock ; chain off of the list
838 ; exit with 'C' clear
839
840; $else ; none on free list
841 JMP SHORT $$EN1
842$$IF1:
843
844 mov ax,error_sharing_buffer_exceeded ; None on free list, give up until
845 stc ; garbage collector is ready
846
847; $endif
848$$EN1:
849
850 ret
851
852 EndProc OFL
853
854 Break <CPS - close process SFT>
855
856;******************* START OF SPECIFICATIONS ***********************************
857;
858; CPS - close process SFT.
859;
860; During maintenance, it is necessary to close a
861; file given ONLY the SFT. This necessitates walking all PDB's JFN
862; tables looking for the SFN. The difficult part is in generating the
863; SFN from the SFT. This is done by enumerating SFT's and comparing for
864; the correct SFT. Finding all PDBs is easy: walk arena and check
865; owner fields
866;
867; Inputs: ThisSFT points to SFT of interest
868; Outputs: Handle is closed on user
869; Registers Revised: none
870;
871;******************* END OF SPECIFICATIONS *************************************
872
873 Procedure CPS,NEAR
874
875 ASSUME DS:NOTHING,ES:NOTHING
876
877 SaveReg <DS,SI,ES,DI,AX,BX,CX>
878
879 lds si,ThisSFT
880 xor bx,bx
881cps01:
882
883 CallInstall SFFromSFN,multDOS,22,bx,bx
884
885 jc cps31 ; no more SFN's. Must be FCB.
886
887 CallInstall PointComp,multDOS,20
888
889 jz cps02 ; found matching SFN, go scan.
890 inc bx ; did not match, go back for more
891 jmp cps01
892 ;---------------------------------------
893 ; BL is the sfn we want to find. Walk
894 ; the memory arena enumerating all PDB's
895 ; and zap the handle tables for the
896 ; specified sfn.
897 ;---------------------------------------
898cps02:
899 mov al,bl
900 mov ds,Arena_Head ; get first arena pointer
901
902 ;---------------------------------------
903 ; DS:[0] is the arena header.
904 ; AL is sfn to be closed
905 ;---------------------------------------
906cps1:
907 mov cx,ds:[arena_owner]
908 mov bx,ds
909 inc bx ; is the owner the same as the current
910 cmp cx,bx ; block?
911 jnz cps2 ; no, go skip some more...
912
913 ;---------------------------------------
914 ; CX:0 is the correct pointer to a PDB.
915 ;---------------------------------------
916 push ds
917 mov ds,cx
918 ;---------------------------------------
919 ; Given a PDB at DS:0, scan his handle
920 ; table and then loop through the next
921 ; PDB link.
922 ;---------------------------------------
923cps15:
924 call CPJ ; free for this PDB
925 lds cx,DS:[PDB_Next_PDB] ; advance to next
926 cmp cx,-1
927 jnz cps15 ; there is another link to process
928 pop ds
929 ;---------------------------------------
930 ; We have processed the current
931 ; allocation block pointed to by DS.
932 ; DS:[0] is the allocation block
933 ;---------------------------------------
934cps2:
935 cmp ds:[arena_signature],arena_signature_end
936 jz cps3 ; no more blocks to do
937 mov bx,ds ; get current address
938 add bx,DS:[Arena_size] ; add on size of block
939 inc bx ; remember size of header
940 mov ds,bx ; link to next
941 jmp cps1
942 ;---------------------------------------
943 ; Just for good measure, use CurrentPDB
944 ; and clean off him
945 ;---------------------------------------
946cps3:
947 mov ds,CurrentPDB
948
949 call CPJ
950
951cps31:
952
953 RestoreReg <
954
955 RestoreReg <CX,BX,AX,DI,ES,SI,DS>
956
957 ret
958
959 EndProc CPS
960
961;******************* START OF SPECIFICATIONS ***********************************
962;
963; CPJ -
964;
965; Scan JFN table for SFT # and put in -1 if found
966;
967; Input: DS:0 is PDB
968; AL is SFT index # of interest
969;
970; Output: None
971;
972; Uses: Flags,CX,ES,DI
973;
974;******************* END OF SPECIFICATIONS *************************************
975
976 Procedure CPJ,NEAR
977
978 assume ds:nothing,es:nothing
979
980 mov cx,ds:[PDB_JFN_length]
981 les di,ds:[PDB_JFN_pointer]
982 cld
983cpj1: repne scasb
984
985 retnz ; none found
986
987 mov byte ptr es:[di-1],-1 ; free this
988 jcxz CPJret ; Found one in last JFN entry
989 jmp cpj1 ; keep looking
990CPJret:
991
992 ret
993
994 EndProc CPJ
995
996 Break <SFM - convert an mft pointer into a serial number>
997
998;******************* START OF SPECIFICATIONS ***********************************
999;
1000; SFM - convert a pointer to a mft entry into the serial number for that
1001; entry. We keep these around to see if a FCB really points to the correct
1002; SFT.
1003;
1004; Inputs: BX is the mft pointer
1005; Outputs: BX is the serial number
1006; Registers Revised: none
1007;
1008;******************* END OF SPECIFICATIONS *************************************
1009
1010 Procedure SFM,NEAR
1011
1012 ASSUME CS:SHARE,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
1013
1014 mov bx,cs:[bx].mft_serl
1015
1016 ret
1017
1018 EndProc SFM
1019
1020 Break <ShChk - check a fcb for share related information>
1021
1022;******************* START OF SPECIFICATIONS ***********************************
1023;
1024; ShChk - check a fcb for share related information
1025;
1026; ShChk - checks the reserved field contents of an FCB with a SFT to see
1027; if they represent the same file. The open ref count must be > 0.
1028;
1029; Inputs: DS:SI point to FCB
1030; ES:DI point to SFT
1031; Outputs: Carry Set if contents do not match
1032; Carry clear if contents match
1033; BX has first cluster
1034; Registers Revised: none
1035;
1036;******************* END OF SPECIFICATIONS *************************************
1037
1038 Procedure ShChk,NEAR
1039
1040 ASSUME CS:SHARE,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
1041
1042 CMP ES:[DI].sf_ref_count,0
1043 JZ BadSFT
1044 MOV BX,ES:[DI].sf_mft ; Local file or dev with sharing
1045
1046 call SFM
1047
1048 CMP BX,[SI].fcb_l_mfs
1049 JNZ BadSFT
1050 MOV BX,[SI].fcb_l_firclus
1051
1052 ret
1053
1054BadSFT: stc
1055
1056 ret
1057
1058 EndProc ShChk
1059
1060 Break <ShSave - save information from SFT into an FCB>
1061
1062;******************* START OF SPECIFICATIONS ***********************************
1063;
1064; ShSave - save information from SFT into an FCB
1065;
1066; ShSave - copy information into the reserved area of an FCB from a SFT.
1067; This is so that we can later match the SFT with the FCB.
1068;
1069; Inputs: ES:DI point to SFT
1070; DS:SI point to FCB
1071; Outputs: FCB reserved field is filled in
1072; BL = FCBSHARE
1073; Registers Revised: AX,BX
1074;
1075;******************* END OF SPECIFICATIONS *************************************
1076
1077 Procedure ShSave,NEAR
1078
1079 ASSUME CS:SHARE,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
1080
1081 MOV AL,ES:[DI].sf_attr ; move attribute (for reopen)
1082 MOV [SI].FCB_l_attr,AL
1083 MOV AX,ES:[DI].sf_firclus ; get first cluster
1084 MOV [SI].FCB_l_firclus,AX
1085 MOV BX,ES:[DI].sf_mft ; get sharing pointer
1086
1087 call SFM
1088
1089 MOV [SI].FCB_l_mfs,BX
1090 MOV BL,FCBSHARE
1091
1092 ret
1093
1094 EndProc ShSave
1095
1096 Break <ShCol - collapse identical handle SFTs in mode 70 only>
1097
1098;******************* START OF SPECIFICATIONS ***********************************
1099;
1100; ShCol - collapse identical handle SFTs in mode 70 only
1101;
1102; ShCol - collapse same 70-mode handles together. This represents network
1103; originated FCBs. Since FCB's are incredibly mis-behaved, we collapse the
1104; SFT's for identical files, thus using a single sft for each file instead
1105; of a separate sft for each instance of the file.
1106;
1107; Note that the redirectors will collapse multiple instances of these
1108; files together. FCB's are pretty misbehaved, so the redirector will
1109; inform us of EACH close done on an FCB. Therefore, we must increment
1110; the ref count each time we see a collapse here.
1111;
1112; Inputs: DS:SI ThisSFT has new sft to find.
1113; Outputs: Carry set - no matching SFT was found
1114; Carry clear - matching SFT was found and all collapsing done.
1115; AX has proper handle
1116; Registers Revised: all.
1117;
1118;******************* END OF SPECIFICATIONS *************************************
1119
1120 Procedure ShCol,NEAR
1121
1122 ASSUME CS:SHARE,DS:NOTHING,ES:NOTHING,SS:DOSGROUP
1123
1124 ;---------------------------------------
1125 ; Collapse the files ONLY if
1126 ; the mode is for net FCB's
1127 ;---------------------------------------
1128
1129 MOV AL,BYTE PTR [SI].sf_mode
1130 AND AL,sharing_mask
1131 CMP AL,sharing_net_FCB
1132 JNZ UseJFN
1133
1134 ;---------------------------------------
1135 ; In share support
1136 ;---------------------------------------
1137
1138 XOR BX,BX ; for (i=0; sffromsfn(i); i++) {
1139OpenScan:
1140
1141 CallInstall SFFromSFN,multDOS,22,bx,bx
1142
1143 JC UseJFN
1144
1145 CallInstall PointComp,multDOS,20 ; if (!pointcomp (s,d))
1146
1147 JZ OpenNext
1148 CMP ES:[DI].sf_ref_count,0
1149 JZ OpenNext
1150 MOV AX,ES:[DI].sf_mode
1151 CMP AX,[SI].sf_mode
1152 JNZ OpenNext
1153 MOV AX,ES:[DI].sf_mft
1154 CMP AX,[SI].sf_mft
1155 JNZ OpenNext
1156 MOV AX,WORD PTR ES:[DI].sf_UID
1157 CMP AX,WORD PTR [SI].sf_uid
1158 JNZ OpenNext
1159 MOV AX,WORD PTR ES:[DI].sf_pid
1160 CMP AX,WORD PTR [SI].sf_pid
1161 JZ OpenFound
1162OpenNext:
1163 INC BX
1164 JMP OpenScan
1165 ;--------------------------------------
1166 ; DS:SI points to an sft which is a
1167 ; duplicate of that found in
1168 ; ES:DI is the older one.
1169 ;
1170 ; We call mftclose to release the
1171 ; appropriate info.
1172 ;--------------------------------------
1173OpenFound:
1174 MOV [SI].sf_ref_count,0 ; free 'new' sft
1175
1176 SaveReg <DS,SI,ES,DI,BX>
1177
1178 Context DS
1179
1180 LES DI,ThisSFT
1181
1182 call MFTClose
1183
1184 RestoreReg <AX,DI,ES,SI,DS>
1185
1186 ASSUME DS:NOTHING
1187
1188 INC ES:[DI].sf_ref_count ; d->refcount++;
1189 XOR BX,BX ; find jfn with sfn as contents
1190JFNScan:
1191
1192 CallInstall pJFNFromHandle,multDOS,32,AX,AX
1193
1194 JC UseJFN ; ran out of handles?
1195 CMP AL,BYTE PTR ES:[DI] ; does JFN have SFN?
1196 jz JFNfound ; YES, go return JFN
1197 INC BX ; no, look at next
1198 JMP JFNScan
1199JFNFound:
1200 LDS SI,pJFN
1201 MOV BYTE PTR [SI],0FFh ; free JFN
1202 MOV AX,BX ; return JFN
1203
1204 ret
1205
1206UseJFN:
1207 MOV AX,JFN
1208
1209 ret
1210
1211 EndProc ShCol
1212
1213 Break <ShCloseFile - close a particular file for a particular UID/PID>
1214
1215;******************* START OF SPECIFICATIONS ***********************************
1216;
1217; ShCloseFile - close a particular file for a particular UID/PID
1218;
1219; ShCloseFile - Compatability mode programs will often delete files that
1220; they had open. This was perfectly valid in the 2.0 days, but this
1221; presents a reliability problem in the network based operating environment.
1222; As a result, both RENAME and DELETE will call us to see if the file is
1223; open by is only. If it is not open or is open by us only, we close it.
1224; Note that we will ONLY close compatability SFTs.
1225; Otherwise, we signal and error.
1226;
1227; Inputs: WFT_Start has a DOSGROUP offset to the file name
1228; DS is DOSGroup
1229; Outputs: nothing relevant.
1230; Registers Revised: None.
1231;
1232;******************* END OF SPECIFICATIONS *************************************
1233
1234 Procedure ShCloseFile,NEAR
1235
1236 ASSUME DS:DOSGroup,ES:NOTHING,SS:DOSGroup
1237
1238 SaveReg <AX,BX,CX,DX,SI,DI,BP,DS,ES>
1239
1240 EnterCrit critShare
1241
1242ShCl:
1243 MOV SI,WFP_Start
1244 XOR AL,AL
1245
1246 call FNM ; attempt to find name in list
1247
1248 ASSUME DS:NOTHING
1249
1250 JC ShCloseDone ; can't find, signal success
1251
1252 ;--------------------------------------
1253 ; We have found a file in the MFT.
1254 ; Walk the open sft list to find
1255 ; the SFTs for the current UID/PID.
1256 ;--------------------------------------
1257 MOV CX,DS
1258 LDS SI,[BX].mft_sptr
1259ShClCheck:
1260 MOV AX,Proc_ID
1261 CMP [SI].sf_PID,AX
1262 JNZ ShCloseDone
1263 MOV AX,User_ID
1264 CMP [SI].sf_UID,AX
1265 JNZ ShCloseDone
1266 MOV AX,[SI].sf_mode
1267 AND AX,sharing_mask
1268 CMP AX,sharing_net_fcb
1269 jz ShClNext
1270 CMP AX,sharing_compat
1271 jnz ShCloseDOne
1272ShClNext:
1273 LDS SI,[SI].sf_chain
1274 OR SI,SI
1275 JNZ ShClCheck
1276 MOV DS,CX
1277 LDS SI,[BX].mft_sptr
1278 ;--------------------------------------
1279 ; Everything matches. Set up ThisSFT
1280 ; and walk the chain from the beginning.
1281 ;--------------------------------------
1282 MOV WORD PTR ThisSFT,SI
1283 MOV WORD PTR ThisSFT+2,DS
1284 ;--------------------------------------
1285 ; Close all handles for this SFT
1286 ;--------------------------------------
1287 call CPS
1288 ;--------------------------------------
1289 ; Close the sft itself.
1290 ;--------------------------------------
1291 Context DS
1292
1293 CallInstall DOS_Close,multDos,1
1294 ;--------------------------------------
1295 ; The SFT may be free and we have no
1296 ; idea where the next is. Go and loop
1297 ; all over.
1298 ;--------------------------------------
1299 JMP ShCl
1300 ;--------------------------------------
1301 ; There are no more SFTs to close. Leave
1302 ;---------------------------------------
1303ShCloseDone:
1304
1305 LeaveCrit critShare
1306
1307 STC
1308
1309 RestoreReg <ES,DS,BP,DI,SI,DX,CX,BX,AX>
1310
1311 ret
1312
1313 EndProc ShCloseFile
1314
1315 .xall
1316 Break <ShSU - update all SFTs for a specified change>
1317;******************* START OF SPECIFICATIONS ***********************************
1318;
1319; NAME: ShSU - update all SFTs for a specified change>
1320;
1321; FUNCTION: In a shared environment, we want to propogate the SFT
1322; changes for a particular file to all other SFTs for that
1323; file. The types of things we propogate are:
1324;
1325; - Time of last write - we only do this on CLOSE and on
1326; FILETIMES.
1327;
1328; - Size and allocation information - we do this ONLY when
1329; we change sf_size.
1330;
1331; We achieve this by walking the linked list of SFTs for the
1332; file. See PSEUDOCODE below
1333;
1334; INPUT: ES.DI has SFT that was just Revised.
1335; AX = 0 for updating of time from ES:DI into old sfts
1336; AX = 1 for updating of size/allocation for growth from ES:DI
1337; AX = 2 for updating of size/allocation for shrink from ES:DI
1338; AX = 3 for new instance copy into ES:DI
1339; AX = 4 for update of codepage and high attribute
1340;
1341; OUTPUT: All relevant SFTs are updated.
1342;
1343; REGISTERS USED: All except ES:DI and DS:SI
1344; (NOT RESTORED)
1345;
1346; LINKAGE: DOS Jump Table
1347;
1348; EXTERNAL Invoke: New_Sft, Call_IFS
1349; REFERENCES: Callinstall
1350;
1351; NORMAL -
1352; EXIT:
1353;
1354; ERROR -
1355; EXIT:
1356;
1357; CHANGE 04/15/87 - Major overhaul and IFS support
1358; LOG:
1359;
1360;******************* END OF SPECIFICATIONS *************************************
1361;******************+ START OF PSEUDOCODE +**************************************
1362;
1363; START ShSU
1364;
1365; if not a device and
1366; if not a network
1367; search
1368; if our SFT
1369; advance to next SFT
1370; endif
1371; leave if no more SFT's
1372; exitif cx = 3
1373; invoke New_Sft
1374; orelse
1375; if cx = 0
1376; update time
1377; update date
1378; if non - FAT file system
1379; call IFSFUNC
1380; endif
1381; else cx = 1 or 2
1382; update size
1383; if non - FAT file system
1384; call IFSFUNC
1385; else
1386; update first cluster
1387; if cx = 2 or
1388; if lstclus un-set from create
1389; update cluster position
1390; update last cluster
1391; endif
1392; endif
1393; endif
1394; advance to next SFT
1395; endloop
1396; endsearch
1397; endif
1398; return
1399;
1400; END ShSU
1401;
1402;******************+ END OF PSEUDOCODE +**************************************
1403
1404 Procedure ShSU,near
1405
1406 ASSUME DS:NOTHING,ES:NOTHING
1407
1408 nop
1409; int 3
1410 nop
1411
1412ifs_flag equ 8000h ; ;AN000;
1413 ;---------------------------------------
1414 ; Do nothing for device or network
1415 ;---------------------------------------
1416 mov bx,es:[di].sf_mode
1417 and bx,sf_isnet + devid_device
1418
1419; $if z,and,long ; if not device and ;AC000;
1420 JZ $$XL1
1421 JMP $$IF4
1422$$XL1:
1423
1424 mov bx,es:[di].sf_MFT
1425 or bx,bx
1426
1427; $if nz,,long ; if not network ;AC000;
1428 JNZ $$XL2
1429 JMP $$IF4
1430$$XL2:
1431
1432 EnterCrit critShare
1433 ;---------------------------------------
1434 ; Walk the sft chain for this file and
1435 ; skip the current SFT (ES:DI)
1436 ;---------------------------------------
1437 SaveReg <DS,SI>
1438
1439 lds si,cs:[bx].MFT_SPTR
1440 mov cx,ax
1441
1442; $search ; ;AC000;
1443$$DO5:
1444
1445 CallInstall PointComp,multDOS,20 ; pointers different?
1446
1447; $if z ; if ourselves ;AC000;
1448 JNZ $$IF6
1449
1450 lds si,[si].sf_chain ; move to next ;AC000;
1451
1452; $endif ; endif - ourselves ;AC000;
1453$$IF6:
1454
1455 or si,si
1456
1457; $leave z ; ;AC000;
1458 JZ $$EN5
1459
1460 ;---------------------------------------
1461 ; CX = 0 for updating of time
1462 ; CX = 1 for updating of size/allocation
1463 ; for growth
1464 ; CX = 2 for updating of size/allocation
1465 ; for shrink
1466 ; CX = 3 for new instance copy.
1467 ;---------------------------------------
1468 cmp cx,2 ; ;AC000;
1469
1470; $exitif a ; ;AC000;
1471 JNA $$IF5
1472 ;---------------------------------------
1473 ; CX = 3 for new instance copy.
1474 ; CX = 4 for codepage and high attrib update
1475 ;---------------------------------------
1476 cmp cx,3 ; cx = 3 ? ;an000;
1477; $if e ; yes ;an000;
1478 JNE $$IF10
1479 call New_Sft ; ;AN000;
1480;; $else ; cx = 4 ;an000;
1481;; call New_CP_Attrib ; update codepage and high attrib ;an000;
1482; $endif ; ;an000;
1483$$IF10:
1484
1485; $orelse ; ;AC000;
1486 JMP SHORT $$SR5
1487$$IF5:
1488
1489 or cx,cx
1490
1491; $if z ; if cx = 0 then ;AC000;
1492 JNZ $$IF13
1493 ;---------------------------------------
1494 ; CX = 0 for updating of time
1495 ;
1496 ; Copy time from ES:DI into DS:SI
1497 ;---------------------------------------
1498 mov bx,es:[di].sf_time
1499 mov [si].sf_time,bx
1500 mov bx,es:[di].sf_date
1501 mov [si].sf_date,bx
1502 test [si].sf_flags,ifs_flag ; ;AN000;
1503
1504; $if nz ; if non-FAT ;AC003;
1505 JZ $$IF14
1506
1507 call Call_IFS ; tell IFS of SFT change ;AN000;
1508
1509; $endif ; endif non- FAT ;AN000;
1510$$IF14:
1511
1512; $else ; else - must be >0 and <2 ;AC000;
1513 JMP SHORT $$EN13
1514$$IF13:
1515 ;---------------------------------------
1516 ; CX = 1 for updating of size/allocation
1517 ; for growth
1518 ; CX = 2 for updating of size/allocation
1519 ; for shrink
1520 ;
1521 ; We always copy size and firclus
1522 ;---------------------------------------
1523 mov bx,word ptr es:[di].sf_size
1524 mov word ptr [si].sf_size,bx
1525 mov bx,word ptr es:[di].sf_size+2
1526 mov word ptr [si].sf_size+2,bx
1527 test [si].sf_flags,ifs_flag ; ;AN000;
1528
1529; $if nz ; if non-FAT ;AC003;
1530 JZ $$IF17
1531
1532 invoke Call_IFS ; tell IFS of SFT change ;AN000;
1533
1534; $else ; else - its FAT ;AN000;
1535 JMP SHORT $$EN17
1536$$IF17:
1537
1538 mov bx,es:[di].sf_firclus
1539 mov [si].sf_firclus,bx
1540 cmp cx,2 ; ;AC000;
1541
1542; $if z,or ; if SFT is shrinking or ;AC000;
1543 JZ $$LL19
1544
1545 cmp [si].sf_lstclus,0 ; lstclus UN-set from a create? ;AC000;
1546
1547; $if z ; If it is, set lstclus and cluspos too;AC000;
1548 JNZ $$IF19
1549$$LL19:
1550 ;---------------------------------------
1551 ; Shrink the file, move in new cluspos
1552 ; and lstclus
1553 ;---------------------------------------
1554 mov [si].sf_cluspos,0 ; retrace from start
1555 mov [si].sf_lstclus,bx ; ditto
1556
1557; $endif ; endif - set lstclus and cluspos ;AC000;
1558$$IF19:
1559
1560; $endif ; endif FAT ;AN000;
1561$$EN17:
1562
1563; $endif ; enndif - > 0 ;AC000;
1564$$EN13:
1565 ;---------------------------------------
1566 ; Link to next SFT
1567 ;---------------------------------------
1568 lds si,[si].sf_chain
1569
1570; $endloop ; ;AC000;
1571 JMP SHORT $$DO5
1572$$EN5:
1573
1574; $endsrch ; ;AC000;
1575$$SR5:
1576 ;---------------------------------------
1577 ; All Done
1578 ;---------------------------------------
1579 RestoreReg <SI,DS>
1580
1581 LeaveCrit critShare
1582
1583; $endif ; endif - device and network ;AC000;
1584$$IF4:
1585
1586 ret
1587
1588 EndProc ShSU
1589
1590 Break <New_Sft - update a new SFT>
1591
1592;******************* START OF SPECIFICATIONS ***********************************
1593;
1594; NAME: New_Sft - update a new SFT
1595;
1596; FUNCTION: Copy all SFT information into a NEW sft of a SHARED file.
1597;
1598;
1599; INPUT: ES.DI has SFT that was just Revised.
1600; DS:SI has SFT that is to be updated
1601;
1602; OUTPUT: SFT is updated.
1603;
1604; REGISTERS USED: AX, BX
1605; (NOT RESTORED)
1606;
1607; LINKAGE: Invoked by: ShSU
1608;
1609; EXTERNAL Invoke: Call_IFS
1610; REFERENCES:
1611;
1612; CHANGE 04/15/87 - First release
1613; LOG:
1614;
1615;******************* END OF SPECIFICATIONS *************************************
1616;******************+ START OF PSEUDOCODE +**************************************
1617;
1618; START New_Sft
1619;
1620; update time
1621; update date
1622; update size
1623; if non - FAT file system
1624; call IFSFUNC
1625; else
1626; update first cluster
1627; update cluster position
1628; update last cluster
1629; endif
1630; return
1631;
1632; END New_Sft
1633;
1634;******************+ END OF PSEUDOCODE +**************************************
1635
1636 Procedure New_Sft,near ; ;AN000;
1637
1638 mov bx,[si].sf_time ; update time
1639 mov es:[di].sf_time,bx
1640 mov bx,[si].sf_date ; update date
1641 mov es:[di].sf_date,bx
1642 mov bx,word ptr [si].sf_size ; update size
1643 mov word ptr es:[di].sf_size,bx
1644 mov bx,word ptr [si].sf_size+2
1645 mov word ptr es:[di].sf_size+2,bx
1646 test es:[di].sf_flags,ifs_flag ; ;AN000;
1647
1648; $if nz ; if non-FAT ;AC003;
1649 JZ $$IF26
1650
1651 call Call_IFS ; tell IFS of SFT change ;AN000;
1652
1653; $else ; else - its FAT ;AN000;
1654 JMP SHORT $$EN26
1655$$IF26:
1656
1657 mov bx,[si].sf_firclus ; update first cluster
1658 mov es:[di].sf_firclus,bx
1659 mov es:[di].sf_cluspos,0 ; retrace from start
1660 mov es:[di].sf_lstclus,bx ; ditto
1661
1662; $endif ; endif FAT ;AN000;
1663$$EN26:
1664
1665 ret ; we'er done ;AN000;
1666
1667 EndProc New_Sft ; ;AN000;
1668
1669 Break <New_CP_Attrib - update the codepage and attrib in SFT>
1670
1671;******************* START OF SPECIFICATIONS ***********************************
1672;
1673; NAME: New_CP_Attrib - Update codepage and attrib in SFT
1674;
1675; FUNCTION: Copy all codepage and attrib into SFT of a SHARED file.
1676;
1677;
1678; INPUT: ES.DI has SFT that was just Revised.
1679; DS:SI has SFT that is to be updated
1680;
1681; OUTPUT: SFT is updated.
1682;
1683; REGISTERS USED: AX, BX
1684; (NOT RESTORED)
1685;
1686; LINKAGE: Invoked by: ShSU
1687;
1688; EXTERNAL Invoke: Call_IFS
1689; REFERENCES:
1690;
1691; CHANGE 10/06/87 - First release - D. M. Sewell
1692; LOG:
1693;
1694;******************* END OF SPECIFICATIONS *************************************
1695;******************+ START OF PSEUDOCODE +**************************************
1696;
1697; START New_CP_Attrib
1698;
1699; Update codepage
1700; Update high attribute
1701; $if ifs_flag
1702; call Call_IFS
1703; $endif
1704; return
1705;
1706; END New_CP_Attrib
1707;
1708;******************+ END OF PSEUDOCODE +**************************************
1709
1710;; Procedure New_CP_Attrib,near ; ;AN000;
1711
1712;; mov bx,es:[di].SF_Codepage ; update codepage ;an000;
1713;; mov [si].SF_Codepage,bx ;an000; dms;
1714;; mov bl,es:[di].SF_Attr_Hi ; update high attribute ;an000;
1715;; mov [si].SF_Attr,bl ;an000; dms;
1716;; test es:[di].sf_flags,ifs_flag ; ;AN000;
1717
1718;; $if nz ; if non-FAT ;AC003;
1719
1720;; call Call_IFS ; tell IFS of SFT change ;AN000;
1721
1722;; $endif ; endif FAT ;AN000;
1723
1724;; ret ; we'er done ;AN000;
1725
1726;; EndProc New_CP_Attrib ; ;AN000;
1727
1728
1729 Break <Call_IFS - warn IFS that SFT has changed>
1730
1731;******************* START OF SPECIFICATIONS ***********************************
1732;
1733; NAME: Call_IFS - warn IFS that SFT has changed
1734;
1735; FUNCTION: Call IFS thru 2F interupt.
1736;
1737; INPUT: DS.SI points to SFT that was just Revised.
1738;
1739; OUTPUT: none
1740;
1741; REGISTERS USED: AX
1742; (NOT RESTORED)
1743;
1744; LINKAGE: Invoked by: ShSU, New_SFT
1745;
1746; EXTERNAL Callinstall
1747; REFERENCES:
1748;
1749; CHANGE 04/15/87 - First release
1750; LOG:
1751;
1752;******************* END OF SPECIFICATIONS *************************************
1753;******************+ START OF PSEUDOCODE +**************************************
1754;
1755; START Call_IFS
1756;
1757; set up for INT
1758; INT 2F
1759; return
1760;
1761; END Call_IFS
1762;
1763;******************+ END OF PSEUDOCODE +**************************************
1764
1765 Procedure Call_IFS,near ; ;AN000;
1766
1767 CallInstall BlockUpdate,MultIFS,44,CX,CX ; ;AC005;
1768
1769 ret ; ;AN000;
1770
1771 EndProc Call_IFS ; ;AN000;
1772
1773 Break <Internal error routines>
1774
1775;******************* START OF SPECIFICATIONS ***********************************
1776;
1777; INTERR - INTernal ERRor routines
1778;
1779;******************* END OF SPECIFICATIONS *************************************
1780
1781 Procedure INTERR,NEAR
1782
1783 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
1784
1785 SaveReg <BX,SI,DS> ; save registers that get clobbered
1786
1787 push cs ; gain addressability
1788 pop ds
1789 mov si,ax ; get message to print
1790
1791 call gout
1792
1793 off si,IntErrMSG
1794
1795 call gout
1796
1797 RestoreReg <ds,si,bx>
1798
1799INTERRL:jmp INTERRL ; hang here - we're sick
1800
1801gout: lodsb
1802 or al,al
1803 retz
1804 mov ah,14
1805 int 10h
1806 jmp gout
1807
1808IntErrMsg DB "Share: Internal error", 13, 10, 0
1809
1810 EndProc INTERR
1811
1812 Break <INT 2F handler>
1813
1814 IF installed
1815
1816 public skip_check
1817
1818skip_check db 0 ; start with do checking
1819
1820state_change db 0 ; SHARE change in state flag
1821 ; 0 - no change in state
1822 ; 1 - SHARE load state has changed
1823
1824CONT DD ?
1825
1826INT2F PROC FAR
1827
1828 ASSUME CS:SHARE,DS:NOTHING,ES:NOTHING,SS:NOTHING
1829 cmp ah,multSHARE
1830 jnz ContJ
1831
1832; Its for SHARE! Check to see who is calling:
1833
1834; AL =
1835; 81h its us, with /NC - set skip_check
1836; - return 0F0h - end init
1837; 80h its us
1838; if skip_check is reset
1839; - return 0FFh - loaded
1840; if skip_check is set
1841; - reset skip_check
1842; - return 0F0h - end init
1843;
1844; 40h its IFSFUNC - return 0FFh - loaded
1845;
1846; 00h its anyone else - clear skip_check
1847; - return 0FFh - loaded
1848
1849 test al,80h ; is it share? ;AN010;
1850; $if nz ; if it is ;AN010;
1851 JZ $$IF29
1852 and al,1 ; is /NC set ;AN010;
1853 mov al,0F0H ; assume a quiet return ;AN010;
1854; $if nz ; if it is ;AN010;
1855 JZ $$IF30
1856 cmp skip_check,1 ; is skip_check set ? ;AN011;
1857; $if ne ; if it is ;AN011;
1858 JE $$IF31
1859 mov state_change,1 ; set the change state flag ;AN011;
1860; $endif ; ;AN011;
1861$$IF31:
1862 mov skip_check,1 ; set skip_check ;AN010;
1863; $else ; /NC not requested ;AN010;
1864 JMP SHORT $$EN30
1865$$IF30:
1866 cmp skip_check,1 ; is skip_check set ? ;AN010;
1867; $if e ; if it is ;AN010;
1868 JNE $$IF34
1869 mov state_change,1 ; set the change state flag ;AN011;
1870 mov skip_check,0 ; reset skip_check ;AN010;
1871; $else ; else , its already clear ;AN010;
1872 JMP SHORT $$EN34
1873$$IF34:
1874 mov al,0FFH ; and we are loaded ;AN010;
1875; $endif ; ;AN010;
1876$$EN34:
1877; $endif ; ;AN010;
1878$$EN30:
1879
1880; $else ; ;AN010;
1881 JMP SHORT $$EN29
1882$$IF29:
1883 cmp al,40h ; is it IFSFUNC? ;AN010;
1884; $if ne ; if it is not ;AN010;
1885 JE $$IF39
1886
1887 or al,al ; loop it any other value caus' ;AC010;
1888Freeze:
1889 jnz freeze ; no one should EVER issue this ;AC010;
1890 cmp skip_check,1 ; is skip_check set ? ;AN010;
1891; $if e ; if it is ;AN011;
1892 JNE $$IF40
1893 mov state_change,1 ; set the change state flag ;AN011;
1894; $endif ; ;AN011;
1895$$IF40:
1896 mov skip_check,0 ; and believe it ! ;AN011;
1897
1898; $endif ; ;AN010;
1899$$IF39:
1900 mov al,0FFH ; else - say we are here ;AN010;
1901; $endif ; ;AN010;
1902$$EN29:
1903 cmp state_change,1 ; SHARE installed state may have change;AN011;d
1904; $if e ; - update DOS ;AN011;
1905 JNE $$IF44
1906 push ax ; ;AN011;
1907 push es ; this is interesting - ;AN011;
1908 MOV AH,Get_In_Vars ; if SHARE =1 and DOS =1 - no change;AN011;
1909 INT 21h ; if SHARE = ;AN011;
1910
1911 ASSUME ES:DOSGROUP
1912
1913 mov al,skip_check ; get the SHARE operating mode ;AN011;
1914 cmp al,1 ; is it a /nc - tell DOS " 1 " ;AN011;
1915; $if ne ; if not ;AN011;
1916 JE $$IF45
1917 dec al ; "full" SHARE - tell DOS " -1 " ;AN011;
1918; $endif ; ;AN011;
1919$$IF45:
1920 MOV fShare,al ; tell DOS we are here ;AN011;
1921 pop es ; ;AN011;
1922 pop ax ; ;AN011;
1923 mov state_change,0 ; REset the change state flag ;AN011;
1924; $endif ; ;AN011;
1925$$IF44:
1926
1927 ASSUME ES:nothing
1928
1929 iret
1930ContJ:
1931 JMP CONT
1932INT2F ENDP
1933
1934 ASSUME CS:SHARE,DS:NOTHING,ES:NOTHING,SS:DOSGroup
1935
1936IRP rtn,<MFT_enter, MFTClose, MFTclU, MFTCloseP, MFTCloN, set_mult_block, clr_mult_block>
1937J&rtn proc far
1938 call rtn
1939 ret
1940j&rtn endp
1941endm
1942
1943IRP rtn,<chk_block, MFT_get, ShSave, ShChk, ShCol, ShCloseFile, ShSU>
1944J&rtn proc far
1945 call rtn
1946 ret
1947j&rtn endp
1948endm
1949
1950IRP sect,<critShare>
1951 Procedure E&sect,NEAR
1952 PUSH AX
1953 MOV AX,8000h+sect
1954 INT int_ibm
1955 POP AX
1956 ret
1957 EndProc E&sect
1958
1959 Procedure L&sect,NEAR
1960 PUSH AX
1961 MOV AX,8100h+sect
1962 INT int_ibm
1963 POP AX
1964 ret
1965 EndProc L&sect
1966 ENDM
1967
1968 ENDIF
1969
1970 BREAK <MFT and Lock Record Data Area>
1971
1972;******************* START OF SPECIFICATIONS ***********************************
1973;
1974; first MFT record
1975;
1976; Note that the name field can have garbage after the trailing
1977; 00 byte. This is because the field might be too long, but
1978; not long enough (at least 16 extra bytes) to fragment.
1979; in this case we copy the length of the string area, not
1980; the length of the string and thus may copy tailing garbage.
1981;
1982;******************* END OF SPECIFICATIONS *************************************
1983
1984PoolSize = 2048
1985
1986 PUBLIC MFT
1987
1988MFT DB 0 ; free
1989 DW PoolSize ; PoolSize bytes long
1990
1991 IF not Installed
1992
1993 DB (PoolSize-3) DUP(0) ; leave rest of record
1994MEND DB -1 ; END record
1995
1996lck1 DW 0 ; link
1997 DB SIZE RLR_entry-2 DUP(0)
1998lck2 DW OFFSET DOSGROUP:lck1 ; link
1999 DB SIZE RLR_entry-2 DUP(0)
2000lck3 DW OFFSET DOSGROUP:lck2 ; link
2001 DB SIZE RLR_entry-2 DUP(0)
2002lck4 DW OFFSET DOSGROUP:lck3 ; link
2003 DB SIZE RLR_entry-2 DUP(0)
2004lck5 DW OFFSET DOSGROUP:lck4 ; link
2005 DB SIZE RLR_entry-2 DUP(0)
2006lck6 DW OFFSET DOSGROUP:lck5 ; link
2007 DB SIZE RLR_entry-2 DUP(0)
2008lck7 DW OFFSET DOSGROUP:lck6 ; link
2009 DB SIZE RLR_entry-2 DUP(0)
2010lck8 DW OFFSET DOSGROUP:lck7 ; link
2011 DB SIZE RLR_entry-2 DUP(0)
2012
2013 CODE ENDS
2014
2015 %out Ignore this END error (blasted assembler)
2016
2017 ENDIF
2018
2019IF Installed
2020
2021 ASSUME CS:SHARE,DS:NOTHING,ES:NOTHING,SS:NOTHING
2022
2023 IF1
2024InitSpace DW PoolSize
2025 ELSE
2026 IF shareinit-MFT LT PoolSize
2027InitSpace DW PoolSize
2028 ELSE
2029InitSpace DW shareinit-MFT
2030 ENDIF
2031 ENDIF
2032InitLocks DW 20
2033
2034
2035JTable LABEL BYTE
2036 DD ?
2037 DD JMFT_Enter ; 1 MFT_enter
2038 DD JMFTClose ; 2 MFTClose
2039 DD JMFTclU ; 3 MFTclU
2040 DD JMFTcloseP ; 4 MFTCloseP
2041 DD JMFTcloN ; 5 MFTCloN
2042 DD JSet_Mult_Block ; 6 Set_Mult_Block
2043 DD JClr_Mult_Block ; 7 Clr_Mult_Block
2044 DD JChk_Block ; 8 Chk_Block
2045 DD JMFT_Get ; 9 MFT_get
2046 DD JShSave ; 10 ShSave
2047 DD JShChk ; 11 ShChk
2048 DD JShCol ; 12 ShCol
2049 DD JShCloseFile ; 13 ShCloseFile
2050 DD JShSU ; 14 ShSU
2051JTableLen = $ - JTable
2052
2053; $SALUT (4,9,17,36)
2054 ;---------------------------------------
2055 ; STRUCTURE TO DEFINE ADDITIONAL
2056 ; COMMAND LINE PARAMETERS
2057 ;---------------------------------------
2058PARMS LABEL DWORD
2059 DW OFFSET PARMSX ; POINTER TO PARMS STRUCTURE
2060 DB 0 ; NO DELIMITER LIST FOLLOWS
2061 DB 0 ; NUMBER OF ADDITIONAL DELIMITERS
2062
2063 ;---------------------------------------
2064 ; STRUCTURE TO DEFINE SORT
2065 ; SYNTAX REQUIREMENTS
2066 ;---------------------------------------
2067PARMSX LABEL BYTE
2068 DB 0,0 ; THERE ARE NO POSITIONAL PARAMETERS
2069 DB 1 ; THERE ARE ONLY ONE TYPE OF SWITCH
2070 DW OFFSET SW ; POINTER TO THE SWITCH DEFINITION AREA
2071 DW 0 ; THERE ARE NO KEYWORDS IN SHARE SYNTAX
2072
2073 ;---------------------------------------
2074 ; STRUCTURE TO DEFINE THE SWITCHES
2075 ;---------------------------------------
2076
2077SW LABEL WORD
2078 DW 08001H ; MUST BE NUMERIC
2079 DW 0 ; NO FUNCTION FLAGS
2080 DW OFFSET SWITCH_BUFF ; PLACE RESULT IN SWITCH BUFFER
2081 DW OFFSET VALUES ; NEED VALUE LIST
2082 DB 3 ; TWO SWITCHES IN FOLLOWING LIST
2083F_SW DB "/F",0 ; /F: INDICATES n FILESPACE REQUESTED
2084L_SW DB "/L",0 ; /L: INDICATES m LOCKS REQUESTED
2085N_SW DB "/NC",0 ; /NC: INDICATES no checking required
2086
2087
2088 ;---------------------------------------
2089 ; VALUE LIST DEFINITION FOR n
2090 ;---------------------------------------
2091
2092VALUES LABEL BYTE
2093 DB 1 ; ONE VALUE ALLOWED
2094 DB 1 ; ONLY ONE RANGE
2095 DB FILE_SWITCH ; IDENTIFY IT AS n
2096 DD 1,65535 ; USER CAN SPECIFY /+1 THROUGH /+65535
2097
2098 ;---------------------------------------
2099 ; RETURN BUFFER FOR SWITCH INFORMATION
2100 ;---------------------------------------
2101; $SALUT (4,17,27,36)
2102
2103SWITCH_BUFF LABEL BYTE
2104SW_TYPE DB ? ; TYPE RETURNED
2105SW_ITEM_TAG DB ? ; SPACE FOR ITEM TAG
2106SW_SYN DW ? ; POINTER TO SWITCH LIST ENTRY
2107SW_VALUE DD ? ; SPACE FOR VALUE
2108
2109; $SALUT (4,4,9,41)
2110
2111 Break <INIT - INITalization routines>
2112
2113;******************* START OF SPECIFICATIONS ***********************************
2114;
2115; INIT - INITalization routines
2116;
2117;******************* END OF SPECIFICATIONS *************************************
2118
2119 Procedure Init,NEAR
2120
2121 PUSH CS
2122 POP DS
2123
2124 ASSUME DS:SHARE
2125
2126 MOV BX,InitSpace
2127
2128 SUB BX,3
2129 MOV SI,OFFSET MFT
2130 MOV WORD PTR [SI+1],BX ; length of first item
2131 ADD SI,BX ; link to end of structure
2132 MOV BYTE PTR [SI],-1 ; signal end
2133 INC SI ; point to next free byte
2134
2135 MOV CX,initlocks ; count for loop
2136 MOV AX,0
2137
2138; $do ; ;AC000;
2139$$DO48:
2140
2141 MOV [SI].RLR_next,AX ; link in previous
2142 MOV AX,SI ; this is now previous
2143 ADD SI,SIZE RLR_Entry ; move to next object
2144
2145; $enddo loop ; ;AC000;
2146 LOOP $$DO48
2147
2148 MOV FreLock,AX ; point to beginning of free list
2149
2150 MOV DX,CS
2151 MOV BX,ES
2152 SUB DX,BX
2153 ADD SI,15
2154 RCR SI,1
2155 SHR SI,1
2156 SHR SI,1
2157 SHR SI,1
2158
2159 ADD SI,DX
2160 PUSH SI ; # of paras for share on stack
2161
2162 MOV AX,(Get_Interrupt_Vector SHL 8) + 2Fh
2163 INT 21h
2164 MOV WORD PTR CONT,BX
2165 MOV WORD PTR CONT+2,ES
2166 MOV AX,(Set_Interrupt_Vector SHL 8) + 2Fh
2167 MOV DX,OFFSET INT2F
2168 INT 21h
2169 ;---------------------------------------
2170 ; Notify the DOS that we are around so that
2171 ; the DOS can make expensive calls to us.
2172 ;---------------------------------------
2173 MOV AH,Get_In_Vars
2174 INT 21h
2175
2176 ASSUME ES:DOSGROUP
2177
2178 mov al,skip_check ; get the SHARE operating mode ;AN011;
2179 cmp al,1 ; is it a /nc - tell DOS " 1 " ;AN011;
2180
2181; $if ne ; if not ;AN011;
2182 JE $$IF50
2183 dec al ; "full" SHARE - tell DOS " -1 " ;AN011;
2184; $endif ;
2185$$IF50:
2186
2187 MOV fShare,al ; tell DOS we are here ;AC011;
2188 ;---------------------------------------
2189 ; Cram in the new jump table
2190 ;---------------------------------------
2191 CLI
2192 MOV SI,OFFSET JTable
2193 MOV DI,OFFSET JShare
2194 MOV CX,JTableLen/2
2195 REP MOVSW
2196 ;---------------------------------------
2197 ; Examine the size of the FCB cache.
2198 ; If it is NOT the system default of 4,0
2199 ; change it (via reallocation) to 16,8.
2200 ; The old table is lost.
2201 ;---------------------------------------
2202 ASSUME DS:NOTHING
2203
2204 CMP KeepCount,0
2205
2206; $if z,and ; if the ",0" part and ;AC000;
2207 JNZ $$IF52
2208
2209 LDS SI,ES:[BX].SYSI_FCB ; point to the existing cache
2210 CMP [SI].sfCount,4
2211
2212; $if z ; if the "4," part then ;AC000;
2213 JNZ $$IF52
2214
2215 ;---------------------------------------
2216 ; Whammo, we need to allocate 16 * size
2217 ; of SF_entry + size of sfTable.
2218 ; Compute this size in paragraphs
2219 ;---------------------------------------
2220 MOV AX,16
2221 MOV CX,size sf_entry
2222 MUL CX
2223 ADD AX,(size sf) - 2
2224 ;---------------------------------------
2225 ; This size is in bytes...
2226 ; Round up to paragraph size
2227 ;---------------------------------------
2228 ADD AX,0Fh
2229 RCR AX,1
2230 SHR AX,1
2231 SHR AX,1
2232 SHR AX,1
2233 ;---------------------------------------
2234 ; AX is the number of paragraphs to add.
2235 ; Word on stack is current TNR size.
2236 ; Make dos point to new table
2237 ;---------------------------------------
2238 MOV WORD PTR ES:[BX].SYSI_FCB,0
2239 MOV WORD PTR ES:[BX].SYSI_FCB+2,SS
2240 POP SI
2241 ADD WORD PTR ES:[BX].SYSI_FCB+2,SI
2242 ;---------------------------------------
2243 ; Initialize table parts, next link
2244 ; and size
2245 ;---------------------------------------
2246 MOV DS,WORD PTR ES:[BX].SYSI_FCB+2
2247 MOV WORD PTR DS:[sfLink],-1
2248 MOV WORD PTR DS:[sfLink+2],-1
2249 MOV DS:[sfcount],16
2250 ;---------------------------------------
2251 ; Set up succeeding LRU size
2252 ;---------------------------------------
2253 MOV KeepCount,8
2254
2255 ADD SI,AX
2256 PUSH SI
2257
2258; $endif ; endif - "4,0" ;AC000;
2259$$IF52:
2260
2261 ;---------------------------------------
2262 ; Clean out the FCB Cache
2263 ;---------------------------------------
2264 LES DI,ES:[BX].SYSI_FCB
2265
2266 ASSUME ES:Nothing
2267
2268 MOV CX,ES:[DI].SFCount
2269 LEA DI,[DI].SFTable
2270
2271; $do ; ;AC000;
2272$$DO54:
2273
2274 MOV ES:[DI].sf_ref_count,0
2275 MOV WORD PTR ES:[DI].sf_position,0
2276 MOV WORD PTR ES:[DI].sf_position+2,0
2277 ADD DI,SIZE sf_entry
2278
2279; $enddo loop ; ;AC000;
2280 LOOP $$DO54
2281
2282 STI
2283
2284 ASSUME ES:NOTHING
2285
2286 XOR BX,BX
2287 MOV CX,5 ; StdIN,StdOUT,StdERR,StdAUX,StdPRN
2288
2289; $do ; Close STD handles before ;AC000;
2290$$DO56:
2291 ; keep process
2292 MOV AH,CLOSE
2293 INT 21H
2294 INC BX
2295
2296; $enddo loop ; ;AC000;
2297 LOOP $$DO56
2298
2299 POP DX ; T+R size in DX
2300 MOV AX,(Keep_Process SHL 8) + 0
2301 INT 21h
2302 MOV AX,(EXIT SHL 8) + 1
2303 INT 21h ; We'er now resident, return to DOS
2304
2305 EndProc Init
2306
2307 Break <SHAREINIT - Share initialization entry point>
2308
2309;******************* START OF SPECIFICATIONS ***********************************
2310;
2311; SHAREINIT - Share initialization entry point
2312;
2313;******************* END OF SPECIFICATIONS *************************************
2314
2315 Procedure SHAREINIT,NEAR
2316
2317 ASSUME CS:SHARE,DS:NOTHING,ES:NOTHING,SS:STACK
2318
2319; int 3
2320 nop
2321 nop
2322
2323
2324 PUSH DS ; save PSP segment for later stack ;AC001;
2325 ; relocation
2326
2327 ;---------------------------------------
2328 ; Load Messages
2329 ;---------------------------------------
2330 call ShLoadMsg ; ;AN000;
2331 ;---------------------------------------
2332 ; At this point, the DOS version is OK.
2333 ; (checked by SYSLOADMSG)
2334 ; Now - Check the DOS data version
2335 ;---------------------------------------
2336; $if c,or ; if not same as us ;AC009;
2337 JC $$LL58
2338
2339 MOV AH,Get_In_Vars
2340 INT 21h
2341
2342 ASSUME ES:DOSGROUP
2343
2344 CMP DataVersion,ShareDataVersion
2345
2346 ASSUME ES:NOTHING
2347
2348; $if ne ; if not same as us ;AC000;
2349 JE $$IF58
2350$$LL58:
2351 mov ax,(Utility_Msg_CLASS shl 8) + Bad_DOS_Ver ; ;AN000;
2352 call ShDispMsg ; ;AN000;
2353; $endif ; endif - not same as us ;AC000;
2354$$IF58:
2355
2356 ;---------------------------------------
2357 ; Deallocate memory if possible
2358 ;---------------------------------------
2359 mov ax,ds:[pdb_environ]
2360 or ax,ax
2361
2362; $if nz ; if > 0 deallocate memory ;AC000;
2363 JZ $$IF60
2364 mov es,ax
2365 mov ah,dealloc
2366 int 21h
2367; $endif ; endif - > 0 deallocate memory ;AC000;
2368$$IF60:
2369
2370 ;---------------------------------------
2371 ; Parse the command line
2372 ;---------------------------------------
2373 call ShComndParse ; ;AN000;
2374 ;---------------------------------------
2375 ; Check to see if share already installed.
2376 ;---------------------------------------
2377 mov al,skip_check ; ;AN010;
2378 or al,80h ; signal its SHARE calling ;AN010;
2379 mov ah,multShare ; ;AC010;
2380 INT 2Fh ; ;AC010;
2381 CMP AL,0FFh ; ;AC010;
2382
2383; $if z ; if we'er already loaded ;AC010;
2384 JNZ $$IF62
2385 mov ax,(UTILITY_MSG_CLASS shl 8) + Sh_Already_Loaded ; ;AC010;
2386 call ShDispMsg ; ;AC010;
2387; $endif ; endif - we'er already loaded ;AC010;
2388$$IF62:
2389
2390 ;---------------------------------------
2391 ; Check to see if share installed and
2392 ; a toggle was just performed
2393 ;---------------------------------------
2394 CMP AL,0F0h ; ;AN010;
2395
2396; $if z ; if we'er already loaded ;AN010;
2397 JNZ $$IF64
2398
2399 MOV AX,(EXIT SHL 8) ; ;AN010;
2400 INT 21h ; Return to DOS with RC = 0 ;AN010;
2401
2402; $endif ; endif - we'er already loaded ;AN010;
2403$$IF64:
2404
2405 ;---------------------------------------
2406 ; All set to initialize the world.
2407 ; Make sure that we have enough memory
2408 ; for everything in our little 64K here.
2409 ; First get avail count of paras.
2410 ;---------------------------------------
2411 pop es ; recover PSP segment ;AC002;
2412 push es ; ;AC002;
2413 MOV BX,CS
2414 MOV AX,ES:[PDB_Block_Len]
2415 SUB AX,BX
2416 ;---------------------------------------
2417 ; AX has the number of paragraphs
2418 ; available to us after the beginning
2419 ; of CS. Max this out at 64K.
2420 ;---------------------------------------
2421 CMP AX,1000h
2422
2423; $if a ; if more than we can handle ;AC000;
2424 JNA $$IF66
2425 MOV AX,1000h ; force it
2426; $endif ; endif - more than we can handle ;AC000;
2427$$IF66:
2428
2429 ;---------------------------------------
2430 ; Take AX paragraphs and convert them
2431 ; into BX:CX bytes.
2432 ;---------------------------------------
2433 XOR BX,BX
2434 SHL AX,1
2435 SHL AX,1
2436 SHL AX,1
2437 SHL AX,1
2438 ADC BX,0
2439 MOV CX,AX
2440 ;---------------------------------------
2441 ; compute in DX:AX, the size
2442 ; requested by the user
2443 ;---------------------------------------
2444 MOV AX,initlocks
2445 MOV SI,size RLR_Entry
2446 MUL SI
2447 ADD AX,OFFSET MFT
2448 ADC DX,0
2449 ADD AX,InitSpace
2450 ADC DX,0
2451 ;---------------------------------------
2452 ; Compare the 32 bit sizes DX:AX and BX:CX.
2453 ; If BX:CX is smaller, then we
2454 ; are out of memory.
2455 ;---------------------------------------
2456
2457 CMP DX,BX ; try upper half first
2458
2459; $if a,or ; if most significant is bigger or ;AC000;
2460 JA $$LL68
2461
2462; $if e,and ; if equal and ;AC000;
2463 JNE $$IF68
2464
2465 CMP AX,CX ;
2466
2467; $if a ; if least significant is bigger ;AC000;
2468 JNA $$IF68
2469$$LL68:
2470
2471 mov ax,(EXT_ERR_CLASS shl 8) + No_Mem_Error ; issue error message ;AN000;
2472
2473 call ShDispMsg ; ;AN000;
2474
2475; $endif ; endif - bigger ;AC000;
2476$$IF68:
2477
2478 ;--------------------------------------
2479 ; Move stack to PSP area. Otherwise we
2480 ; will run into problems with growing
2481 ; the stack into the lock records.
2482 ;---------------------------------------
2483 POP AX ; this is the entry value for DS (PSP) ;AC001;
2484 MOV SS,AX ; ;AC001;
2485 MOV SP,100h ; ;AC001;
2486
2487 ASSUME SS:NOTHING
2488 ;---------------------------------------
2489 ; Continue with rest of initialization
2490 ;---------------------------------------
2491 JMP INIT
2492
2493 EndProc SHAREINIT
2494
2495 Break <ShLoadMsg - Share Load Message>
2496
2497;******************* START OF SPECIFICATIONS ***********************************
2498;
2499; NAME: ShLoadMsg - Share Load Message
2500;
2501; FUNCTION: Load the Share messages into the message buffer.
2502;
2503; INPUT: None
2504;
2505; OUTPUT: Messages loaded into the message buffer and Message
2506; Sevices code initalized
2507;
2508; REGISTERS USED: DI AX CX DX
2509; (NOT RESTORED)
2510;
2511; LINKAGE: Call near
2512;
2513; NORMAL CF = O
2514; EXIT:
2515;
2516; ERROR CF = 1
2517; EXIT:
2518;
2519; CHANGE 04/15/87 - First release
2520; LOG:
2521;
2522;******************* END OF SPECIFICATIONS *************************************
2523
2524 ;---------------------------------------
2525 ; Message Equates
2526 ;---------------------------------------
2527
2528; $SALUT (4,27,34,41)
2529
2530Bad_DOS_Ver equ 1 ; Incorrect DOS version ;AN000;
2531Sh_Already_Loaded equ 2 ; SHARE already loaded message number ;AN000;
2532No_Mem_Error equ 8 ; insufficient memory message number ;AN000;
2533
2534; $SALUT (4,4,9,41)
2535
2536 Procedure ShLoadMsg,near ; ;AN000;
2537 ;---------------------------------------
2538 ; Load the Messages
2539 ;---------------------------------------
2540EXTRN SYSLOADMSG:NEAR ; ;AN000;
2541
2542 call SYSLOADMSG ; ;AN000;
2543
2544; $IF C ; if we have a MAJOR problem ;AN000;
2545 JNC $$IF70
2546 mov ah,dh ; save the class
2547 call ShDispMsg ; ;AN000;
2548 ; For pre DOS 2.0, we may come back
2549 xor ax,ax ; here - so do it the old way
2550 push ss ; just in case
2551 push ax ;
2552
2553xxx proc far ; ;AN000;
2554 ret ; ;AN000;
2555xxx endp ; ;AN000;
2556
2557; $ENDIF ; endif - we have a MAJOR problem ;AN000;
2558$$IF70:
2559
2560
2561 ret ; ;AN000;
2562
2563 EndProc ShLoadMsg ;
2564
2565 Break <ShDispMsg - Share Display Message>
2566
2567;******************* START OF SPECIFICATIONS ***********************************
2568;
2569; NAME: ShDispMsg - Share Display Message
2570;
2571; FUNCTION: Display the messages for share
2572;
2573; INPUT: AX = message number - AH - Class
2574; AL - Number
2575;
2576; OUTPUT: - Messages output to Output Device
2577; - Exit to DOS
2578;
2579; REGISTERS USED: CX DX
2580; (NOT RESTORED)
2581;
2582; LINKAGE: Call near
2583;
2584; NORMAL CF = O
2585; EXIT:
2586;
2587; ERROR CF = 1
2588; EXIT: CX = 0 - INCORRECT DOS VERSION
2589;
2590; CHANGE 04/15/87 - First release
2591; LOG:
2592;
2593;******************* END OF SPECIFICATIONS *************************************
2594
2595; $SALUT (4,27,34,41)
2596
2597 ; The following structure is a
2598 ; SYSMSG SUBLIST control block.
2599 ; It is initalized for the "already
2600 ; installed " message. The parse
2601 ; routine will set it up to work
2602 ; for parseing.
2603SUBLIST LABEL WORD
2604
2605 db sub_size ; size of sublist
2606 db 0 ; reserved
2607msg_offset dw offset SHARE_Name ; insert 'SHARE'
2608
2609msg_segment LABEL WORD
2610
2611IF NOT INSTALLED
2612
2613 dw CODE
2614
2615ELSE
2616
2617 dw SHARE
2618
2619ENDIF
2620
2621num_ins db 1 ; only one insert
2622 db Char_Field_ASCIIZ ; data type flag - ascii z string
2623max_ins db SHARE_Name_Size ; maximum field size
2624min_ins db SHARE_Name_Size ; minimum field size
2625 db " " ; pad character
2626
2627sub_size equ $ - SUBLIST
2628
2629SHARE_Name LABEL WORD
2630
2631 db "SHARE"
2632
2633SHARE_Name_Size equ $ - Share_Name
2634
2635 db 0 ; make it a Z string
2636; $SALUT (4,4,9,41)
2637
2638 Procedure ShDispMsg,near ; ;AN000;
2639 ;---------------------------------------
2640 ; Set up required parameters
2641 ;--------------------------------------
2642 MOV BX,STDERR ;display message on STD ERROR ;AN000;
2643 XOR CX,CX ;no substitution required ;AN000;
2644 XOR DX,DX ;set flags to 0 ;AN000;
2645 DEC DH ;and class to utility ;AN000;
2646 cmp ah,PARSE_ERR_CLASS ;
2647; $if be,and ; ;AC009;
2648 JNBE $$IF72
2649 mov dh,ah ;
2650; $if e ; set up implied substitution ;AC009;
2651 JNE $$IF72
2652
2653 ASSUME DS:nothing,ES:DOSGROUP
2654
2655 mov num_ins,cl ; set number of inserts to 0 ;AN009;
2656 mov BYTE PTR max_ins,030h ; set maximum size of insert ;AN009;
2657 mov BYTE PTR min_ins,1 ; set minimum size of insert ;AN009;
2658 push ds ; set up segment ;AN009;
2659 pop [msg_segment] ; ;AN009;
2660 mov BYTE PTR ds:[si],0 ; turn it into a ASCIIZ string ;AN009;
2661 cmp si,msg_offset ; is there something there? ;AN009;
2662; $if a ; if it is... ;AN009;
2663 JNA $$IF73
2664 inc cx ; ;AN009;
2665; $endif ; ;AN009;
2666$$IF73:
2667; $endif ;
2668$$IF72:
2669 cmp al,Sh_Already_Loaded ; SHARE already loaded message ? ;AN000;
2670; $if e ; if it is... ;AN000;
2671 JNE $$IF76
2672 inc cx ;
2673 mov msg_offset,OFFSET SHARE_name ; ensure the pointer is right ;AN010;
2674; $endif ;
2675$$IF76:
2676 push cs ; ensure that SYSMSG has proper ;AC009;
2677 pop ds ; addressability ;AC009;
2678 lea si,SUBLIST ; point to sublist ;AC009;
2679 xor ah,ah ; ;AN000;
2680
2681 ;--------------------------------------
2682 ; Output the Message
2683 ;---------------------------------------
2684EXTRN SYSDISPMSG:NEAR ; ;AN000;
2685
2686 CALL SYSDISPMSG ; ;AN000;
2687
2688; $IF C ; if error occured ;AN000;
2689 JNC $$IF78
2690
2691 CALL Get_DOS_Error ; a DOS extended error occured ;AN000;
2692 CALL SYSDISPMSG ; try to issue it ;AN000;
2693
2694; $ENDIF ; endif - error occured ;AN000;
2695$$IF78:
2696
2697 MOV AX,(EXIT SHL 8) + 0FFH ; exit to DOS ;AN000;
2698 INT 21h ; ;AN000;
2699
2700 ret ; may return if pre DOS 2.0 ;AN000;
2701
2702 EndProc ShDispMsg ; ;AN000;
2703
2704 BREAK < Get_DOS_Error >
2705
2706;******************* START OF SPECIFICATIONS ***********************************
2707;Routine name: Get_DOS_Error
2708;*******************************************************************************
2709;
2710;Description: Call DOS to obtain DOS extended error #
2711;
2712;Called Procedures: None
2713;
2714;Input: None
2715;
2716;Output: AX = error number
2717; DH = DOS extended error class
2718;
2719;Change History: Created 5/01/87 FG
2720;
2721;******************* END OF SPECIFICATIONS *************************************
2722;******************+ START OF PSEUDOCODE +**************************************
2723;
2724; START Get_DOS_Error
2725;
2726; call DOS for extended error (INT21 GetExtendedError + 00 <5900>)
2727; set up registers for return
2728; ret
2729;
2730; END Get_DOS_Error
2731;
2732;******************- END OF PSEUDOCODE -**************************************
2733
2734 public Get_DOS_Error
2735
2736 Get_DOS_Error PROC NEAR
2737
2738 mov ax,(GetExtendedError shl 8) ; DOS ext. error ;AN000;
2739 xor bx,bx
2740 push es ; ;AN000;
2741 INT 21h ; GetExtendedError + not_used <5900>;AN000;
2742 pop es
2743 mov bx,STDERR ; fix up bx ;AN000;
2744 xor cx,cx ; fix up cx ;AN000;
2745 mov dh,EXT_ERR_CLASS ; set class to dos error
2746
2747 ret ; ;AN000;
2748
2749 ENDPROC Get_DOS_Error
2750
2751 Break <ShComndParse - Share Command line Parser>
2752
2753;******************* START OF SPECIFICATIONS ***********************************
2754;
2755; NAME: ShComndParse - Share Command line Parser
2756;
2757; FUNCTION: Call the DOS PARSE Service Routines to process the command
2758; line. Search for valid switches (/F:n and /L:m) and
2759; update the values for file size and number of locks accordingly
2760;
2761; INPUT: Parameter string from command line in the PSP
2762;
2763; OUTPUT: INITspace and INITlocks are updated.
2764;
2765; REGISTERS USED: ES DI AX BX CX DX
2766; (NOT RESTORED)
2767;
2768; LINKAGE: Call
2769;
2770; NORMAL - If /F:n specified, then INITspace is updated.
2771; EXIT: - If /L:m specified, then INITlocks is updated.
2772;
2773; ERROR If user enters:
2774; EXIT: - any parameter or switch other than /F:n or /L:m
2775; - an invalid value for "n" or "m"
2776; then this routine will display the "Invalid Parameter"
2777; error message and terminate.
2778;
2779; EXTERNAL - System parse service routines
2780; REFERENCES: - INT21 - GET PSP Function Call 062h
2781;
2782; CHANGE 04/15/87 - First release
2783; LOG:
2784;
2785;******************* END OF SPECIFICATIONS *************************************
2786;******************+ START OF PSEUDOCODE +**************************************
2787;
2788; START
2789;
2790; return
2791;
2792; END
2793;
2794;******************- END OF PSEUDOCODE -*************************************
2795
2796; $SALUT (4,27,34,41)
2797
2798 ;--------------------------------------
2799 ; Parse Equates
2800 ;--------------------------------------
2801
2802EOL equ -1 ; Indicator for End-Of-Line ;AN000;
2803NOERROR equ 0 ; Return Indicator for No Errors ;AN000;
2804FILE_SWITCH equ 1 ; this is a file switch ;AN000;
2805LOCK_SWITCH equ 2 ; this is a lock switch ;AN000;
2806Syntax_Error equ 9 ; maximum PARSE error # ;AN000;
2807
2808; $SALUT (4,4,9,41)
2809
2810 Procedure ShComndParse,near ; ;AN000;
2811 ;--------------------------------------
2812 ; Get address of command line
2813 ;--------------------------------------
2814EXTRN SYSPARSE:NEAR ; ;AN000;
2815
2816 MOV SI,0081H ; OFFSET OF COMMAND LINE IN PSP ;AN000;
2817 MOV AH,62H ; AH=GET PSP ADDRESS FUNCTION CALL ;AN000;
2818 INT 21H ; PSP SEGMENT RETURNED IN BX ;AN000;
2819 MOV DS,BX ; PUT PSP SEG IN DS ;AN000;
2820 MOV CX,0 ; NUMBER OF PARMS PROCESSED SO FAR ;AN000;
2821 PUSH CS ; ;AN000;
2822 POP ES ; ;AN000;
2823
2824 ASSUME ES:SHARE ; ;AN000;
2825
2826 ;--------------------------------------
2827 ; Loop for each operand at DS:SI
2828 ;--------------------------------------
2829; $do ; ;AN000;
2830$$DO80:
2831
2832 LEA DI,PARMS ; ADDRESS OF PARSE CONTROLS ;AN000;
2833 MOV DX,0 ; RESERVED ;AN000;
2834 mov msg_offset,si ; save the start scan point ;AC009;
2835 CALL SYSPARSE ; PARSE IT! ;AN000;
2836 CMP AX,EOL ; ARE WE AT END OF COMMAND LINE ? ;AN000;
2837
2838; $leave e ; ;AN000;
2839 JE $$EN80
2840
2841 CMP AX,NOERROR ; ANY ERRORS? ;AN000;
2842
2843; $if ne,or ; if parse says error or ;AN000;
2844 JNE $$LL82
2845
2846 MOV AX,Syntax_Error ; Parse syntax error - just in case ;AN000;
2847 MOV BX,DX ; PLACE RESULT ADDRESS IN BX ;AN000;
2848 CMP BX,OFFSET SWITCH_BUFF ; ;AN000;
2849
2850; $if ne ; if no pointer ;AN000;
2851 JE $$IF82
2852$$LL82:
2853
2854 call PARSE_ERROR ; call error routine ;AN000;
2855
2856; $endif ; endif - error ;AN000;
2857$$IF82:
2858
2859 MOV AX,WORD PTR SW_VALUE ; load the value ;AN000;
2860 MOV BX,SW_SYN ; load pointer to synonym ;AN000;
2861
2862 ;--------------------------------------
2863 ; If user said /F:n, then
2864 ;--------------------------------------
2865
2866 CMP BX,OFFSET F_SW ; IF USER SPECIFIED /F ;AN000;
2867
2868; $if e ; ;AN000;
2869 JNE $$IF84
2870
2871 CMP INITspace,AX ; is default < requested ? ;AN000;
2872
2873; $if b ; if default is < ;AN000;
2874 JNB $$IF85
2875 MOV INITspace,AX ; save the new value ;AN000;
2876; $endif ; endif (else leave it alone) ;AN000;
2877$$IF85:
2878
2879; $else ; else - CHECK FOR LOCKS ;AN000;
2880 JMP SHORT $$EN84
2881$$IF84:
2882
2883 ;---------------------------------------
2884 ; If user said /L:m, then update INITlocks
2885 ;---------------------------------------
2886 CMP BX,OFFSET L_SW ; IF USER SPECIFIED /L ;AN000;
2887
2888; $if e ; if it is ;AN000;
2889 JNE $$IF88
2890
2891 CMP INITlocks,AX ; is default < requested ? ;AN000;
2892
2893; $if b ; if default is < ;AN000;
2894 JNB $$IF89
2895 MOV INITlocks,AX ; save the value ;AN000;
2896; $endif ; endif (else leave it alone) ;AN000;
2897$$IF89:
2898
2899; $else ; else - CHECK FOR TOGGLE ;AN010;
2900 JMP SHORT $$EN88
2901$$IF88:
2902
2903 ;---------------------------------------
2904 ; If user said /NC, then update check_flag
2905 ;---------------------------------------
2906 CMP BX,OFFSET N_SW ; IF USER SPECIFIED /NC ;AN010;
2907; $if ne ; if error ;AC010;
2908 JE $$IF92
2909 MOV AX,Syntax_Error ; Parse syntax error ;AN000;
2910 call PARSE_ERROR ; call error routine ;AN000;
2911; $endif ; endif - error ;AC010;
2912$$IF92:
2913
2914 mov skip_check,1 ; set the skip check flag ;AN010;
2915
2916; $endif ; endif - CHECK FOR TOGGLE ;AN010;
2917$$EN88:
2918
2919; $endif ; endif - CHECK FOR LOCKS ;AN000;
2920$$EN84:
2921
2922; $enddo ; CHECK FOR NEXT PARM ;AN000;
2923 JMP SHORT $$DO80
2924$$EN80:
2925
2926 ret ; NORMAL RETURN TO CALLER ;AN000;
2927
2928 ;---------------------------------------
2929 ; If any other parameter specified,
2930 ; display message and quit
2931 ;---------------------------------------
2932PARSE_ERROR: ; ;AN000;
2933
2934 cmp al,Syntax_Error ; error 1 to 9 ? ;AN000;
2935
2936; $if a ; if parse error ;AN000;
2937 JNA $$IF97
2938
2939 mov al,Syntax_Error ; Parse syntax error
2940
2941; $endif ; endif errors ;AN000;
2942$$IF97:
2943
2944 lea bx,Parse_Ret_Code
2945 xlat cs:[bx]
2946 mov ah,PARSE_ERR_CLASS ; set class to parse error ;AN000;
2947
2948 CALL ShDispMsg ; display the parse error ;AN000;
2949
2950 ret ; this should never be used
2951
2952Parse_Ret_Code label byte
2953
2954 db 0 ; Ret Code 0 -
2955 db 9 ; Ret Code 1 - Too many parameters
2956 db 9 ; Ret Code 2 - Required parameter missing
2957 db 3 ; Ret Code 3 - Invalid switch
2958 db 9 ; Ret Code 4 - Invalid keyword
2959 db 9 ; Ret Code 5 - (reserved)
2960 db 6 ; Ret Code 6 - Parm val out of range
2961 db 9 ; Ret Code 7 - Parameter val not allowed
2962 db 9 ; Ret Code 8 - Parameter val not allowed
2963 db 9 ; Ret Code 9 - Parm format not correct
2964
2965 EndProc ShComndParse ; ;AN000;
2966
2967 include msgdcl.inc
2968
2969 SHARE ENDS
2970
2971 STACK SEGMENT STACK
2972 DB 278 + 128 DUP (?) ; 278 == IBM's ROM requirements
2973 STACK ENDS
2974
2975ENDIF
2976
2977 END shareinit
2978
2979 \ No newline at end of file