summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/XCOPY
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/XCOPY
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/CMD/XCOPY')
-rw-r--r--v4.0/src/CMD/XCOPY/DOS.EQU365
-rw-r--r--v4.0/src/CMD/XCOPY/MAKEFILE49
-rw-r--r--v4.0/src/CMD/XCOPY/XCOPY.ASM3866
-rw-r--r--v4.0/src/CMD/XCOPY/XCOPY.EQU144
-rw-r--r--v4.0/src/CMD/XCOPY/XCOPY.LNK4
-rw-r--r--v4.0/src/CMD/XCOPY/XCOPY.SKL83
-rw-r--r--v4.0/src/CMD/XCOPY/XCOPYPAR.ASM488
-rw-r--r--v4.0/src/CMD/XCOPY/XCPYINIT.ASM1890
-rw-r--r--v4.0/src/CMD/XCOPY/XINITMSG.EQU150
-rw-r--r--v4.0/src/CMD/XCOPY/XMAINMSG.EQU46
10 files changed, 7085 insertions, 0 deletions
diff --git a/v4.0/src/CMD/XCOPY/DOS.EQU b/v4.0/src/CMD/XCOPY/DOS.EQU
new file mode 100644
index 0000000..dcacee7
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/DOS.EQU
@@ -0,0 +1,365 @@
1
2;
3;******************************************************************************
4; DOS Interrupts
5;
6; REVISION HISTORY:
7;
8; PTM P00 - WAIT & LOCK to WAITP & LOCKF for MASM errors. DRM 4/23/87
9;
10; A000 Version 4.00: add PARSER, System Message Handler,
11; Remove the BELL char.,turn off APPEND during TREE
12; search,Extended Attribute processing, Uppercasing
13; and "Out Of Space" during write to standard out.
14; A005 DCR0201 9/11/87 Incorperate new format for EXTENDED
15; ATTRIBUTES.
16;
17;******************************************************************************
18;
19
20Terminate equ 20h
21DOS_Function equ 21h
22Terminate_Address equ 22h
23CNTRL_BREAK equ 23h
24Critical_Error equ 24h
25Disk_Read equ 25h
26Disk_Write equ 26h
27Terminate_Stay_Resident equ 27h
28Printer equ 2Fh
29CHK_APPEND EQU 0B700H ;AN000; CHECK IF APPEND ACTIVE INT 2FH
30GET_APPEND EQU 0B706H ;AN000; Read /X status with INT 2FH
31 ; BX = 0 if /X is not active
32 ; BX = 1 if /X is active
33SET_APPEND EQU 0B707H ;AN000; Set /X status with INT 2FH
34VER_APPEND EQU 0B702H ;AN019; ASK IF DOS VERSION OF APPEND
35EXT_OPEN EQU 6C00H ;AN000; Extended Open function code
36 CREATE_FLAG EQU 0112H ;AN005;FUNCTION CONTROL
37 CREATE_ATTR EQU 0 ;AN000;SEARCH/CREATE ATTRIBUTE
38 CREATE_MODE EQU 0002H ;AC021;CREATE MODE
39 OPN_FLAG EQU 0101H ;AN000;OPEN FUNCTION CONTROL
40 OPN_ATTR EQU 0 ;AN000;OPEN ATTRIBUTE
41 OPN_MODE EQU 0000H ;AN000;OPEN MODE (READ)
42 NUL_LIST EQU -1 ;AN005;JUST TO OPEN
43
44GET_ATTRIB EQU 05702H ;AN000; Get ext. attribute by handle
45 INT_ORDINAL EQU 0 ;AN000;ATTRIBUTE LIST ORDINAL = 0
46 ALL_ATTR EQU -1 ;AN005;TO SELECT ALL THE ATTRIBUTES
47SET_ATTRIB EQU 05704H ;AN012; Set ext. attribute by handle
48;
49;******************************************************************************
50; DOS Function Calls
51;******************************************************************************
52;
53
54Program_Terminate equ 00h
55Keyboard_Input equ 01h
56Display_Output equ 02h
57Auxiliary_Input equ 03h
58Auxiliary_Output equ 04h
59Printer_Output equ 05h
60Direct_Console_IO equ 06h
61Direct_Input_No_Echo equ 07h
62Console_Input_No_Echo equ 08h
63Print_String equ 09h
64Buffered_Keyboard_Input equ 0Ah
65Check_Std_Input_Status equ 0Bh
66Clear_Keyboard_Buffer equ 0Ch
67Disk_Reset equ 0Dh
68Select_Disk equ 0Eh
69FCB_Open equ 0Fh
70FCB_Close equ 10h
71Search_First equ 11h
72Search_Next equ 12h
73FCB_Delete equ 13h
74Sequential_Read equ 14h
75Sequential_Write equ 15h
76FCB_Create equ 16h
77FCB_Rename equ 17h
78Current_Disk equ 19h
79Set_DTA equ 1Ah
80Allocation_Info equ 1Bh
81Allocation_Info_Device equ 1Ch
82Random_Read equ 21h
83Random_Write equ 22h
84File_Size equ 23h
85Set_Relative_Record equ 24h
86Set_Interrupt_Vector equ 25h
87Create_New_PSP equ 26h
88Random_Block_Read equ 27h
89Random_Block_Write equ 28h
90Parse_Filename equ 29h
91Get_Date equ 2Ah
92Set_Date equ 2Bh
93Get_Time equ 2Ch
94Set_Time equ 2Dh
95Verify equ 2Eh
96 Verify_Off equ 02h
97 Verify_On equ 01h
98Set_Verify_On equ 2E01h
99Get_DTA equ 2Fh
100DOS_Version equ 30h
101Terminate_Resident equ 31h
102Get_Interrupt_Vector equ 35h
103Get_Disk_Free_Space equ 36h
104Country_Code equ 38h
105Mkdir equ 39h
106Rmdir equ 3Ah
107Chdir equ 3Bh
108Create equ 3Ch
109Open equ 3Dh
110 Read_Only equ 00h
111 Write_Only equ 01h
112 Read_Write equ 02h
113 Read_Only_Exclusive equ 10h
114 Write_Only_Exclusive equ 11h
115 Read_Write_Exclusive equ 12h
116 Read_Only_Deny_Write equ 20h
117 Write_Only_Deny_Write equ 21h
118 Read_Write_Deny_Write equ 22h
119 Read_Only_Deny_Read equ 30h
120 Write_Only_Deny_Read equ 31h
121 Read_Write_Deny_Read equ 32h
122 Read_Only_Deny_None equ 40h
123 Write_Only_Deny_None equ 41h
124 Read_Write_Deny_None equ 42h
125Close equ 3Eh
126Read equ 3Fh
127Write equ 40h
128Delete equ 41h
129Lseek equ 42h
130 Lseek_Offset equ 00h
131 Lseek_Plus_Offset equ 01h
132 Lseek_End_Offset equ 02h
133Chmod equ 43h
134IOCTL equ 44h
135 Get_Device_Info equ 00h
136 Set_Device_Info equ 01h
137 Read_Channel equ 02h
138 Write_Channel equ 03h
139 Read_Drive_Channel equ 04h
140 Write_Drive_Channel equ 05h
141 Get_Input_Status equ 06h
142 Get_Output_Status equ 07h
143 Is_Removable equ 08h
144 Is_Block_Redirected equ 09h
145 Is_Handle_Redirected equ 0Ah
146 Set_Retry_Count equ 0Bh
147Dup_Handle equ 45h
148Force_Dup_Handle equ 46h
149Get_Current_Directory equ 47h
150Allocate_Memory equ 48h
151Free_Memory equ 49h
152Setblock equ 4Ah
153Exec equ 4Bh
154Exit equ 4Ch
155Waitp equ 4Dh
156Find_First equ 4Eh
157 norm_attr equ 00h
158 incl_read_attr equ 01h
159 incl_h_attr equ 02h
160 incl_h_s_attr equ 06h
161 incl_h_s_dir_attr equ 16h
162Find_Next equ 4Fh
163Get_Verify_Setting equ 54h
164Rename equ 56h
165File_Date_Time equ 57h
166 Get_File_Time equ 00h
167 Set_File_Time equ 01h
168Get_Extended_Error equ 59h
169Create_Temp equ 5Ah
170Create_New equ 5Bh
171File_Access equ 5Ch
172 Lockf equ 00h
173 Unlock equ 01h
174Get_PSP equ 62h
175Upper_Case_String equ 6521h ;AN000;GET EXTENDED COUNTRY INFORMATION
176;
177;******************************************************************************
178; DOS File Handles
179;******************************************************************************
180;
181
182STDIN equ 00h
183STDOUT equ 01h
184STDERR equ 02h
185STDAUX equ 03h
186STDPRN equ 04h
187
188
189;
190;******************************************************************************
191; File's attributes in a Directory entry
192;******************************************************************************
193;
194read_only_file equ 01h
195hidden_file equ 02h
196system_file equ 04h
197has_volume_label equ 08h
198is_subdirectory equ 10h
199archive_on equ 20h
200
201;
202;******************************************************************************
203; Return Codes
204;******************************************************************************
205;
206
207Errorlevel_0 equ 0
208Errorlevel_1 equ 1
209Errorlevel_2 equ 2
210Errorlevel_3 equ 3
211Errorlevel_4 equ 4
212Errorlevel_5 equ 5
213Errorlevel_6 equ 6
214Errorlevel_7 equ 7
215Errorlevel_8 equ 8
216
217;
218;******************************************************************************
219; Extended Error Codes
220;******************************************************************************
221;
222
223Error_No_Error equ 00
224Error_Invalid_Function equ 01
225Error_File_Not_Found equ 02
226Error_Path_Not_Found equ 03
227Error_No_Handles_Left equ 04
228Error_Access_Denied equ 05
229Error_Invalid_Handle equ 06
230Error_Memory_Blocks_Bad equ 07
231Error_Insufficient_Memory equ 08
232Error_Inv_Address equ 09
233Error_Inv_Environment equ 10
234Error_Inv_Format equ 11
235Error_Inv_Access_Code equ 12
236Error_Inv_Data equ 13
237Error_Inv_Drive equ 15
238Error_Rmdir_Current_Dir equ 16
239Error_Not_Same_Device equ 17
240Error_No_More_Files equ 18
241Error_Write_Protect equ 19
242Error_Unknown_Unit equ 20
243Error_Drive_Not_Ready equ 21
244Error_Unknown_Command equ 22
245Error_Data_Error equ 23
246Error_Bad_Request_Len equ 24
247Error_Seek_Error equ 25
248Error_Unknown_Media_Type equ 26
249Error_Sector_Not_Found equ 27
250Error_Out_Of_Paper equ 28
251Error_Write_Fault equ 29
252Error_Read_Fault equ 30
253Error_Gerneral_Failure equ 31
254Error_Sharing_Violation equ 32
255Error_Lock_Violation equ 33
256Error_Inv_Disk_Change equ 34
257Error_FCB_Unavailable equ 35
258Error_File_Exists equ 80
259Error_Cannot_Make equ 82
260Error_Fail_On_Int24 equ 83
261
262;
263;******************************************************************************
264; Extended Error Classes
265;******************************************************************************
266;
267
268Out_Of_Resource equ 1
269Temporary equ 2
270Authorization equ 3
271Internal equ 4
272Hardware_Failure equ 5
273System_Failure equ 6
274Program_Error equ 7
275Not_Found equ 8
276Bad_Format equ 9
277Locked equ 10
278Media equ 11
279Already_Exists equ 12
280Unknown equ 13
281
282;
283;*****************************************************************************
284; Extended Error Actions
285;*****************************************************************************
286;
287
288Retry equ 1
289Delay_Retry equ 2
290User equ 3
291Abort equ 4
292Immediate_Exit equ 5
293Ignore equ 6
294Retry_After_User equ 7
295
296;
297;******************************************************************************
298; Extended Error Locus
299;******************************************************************************
300;
301
302Non_Specific equ 1
303Block_Device equ 2
304Serial_Device equ 4
305Memory equ 5
306
307;
308;******************************************************************************
309; Internal Program Initialization Errors
310;******************************************************************************
311;
312
313Init_Err_DOS_Ver_1 equ 1 ;Bad DOS version prior to 2.0
314Init_Err_DOS_Ver_2 equ 2 ;Bad DOS version 2.0 or above
315Init_Err_Inv_Drive equ 3 ;Invalid drive specification
316Init_Err_Inv_Parm equ 4 ;Invalid parameter
317Init_Err_Inv_Num_Parm equ 5 ;Invalid number of parameters
318Init_Err_Inv_Path equ 6 ;Invalid path
319Init_Err_Insuff_Mem equ 7 ;Insufficient memory
320Init_Err_Inv_Date equ 8 ;Invalid date
321Init_Err_Inv_Time equ 9 ;Invalid time
322Init_Err_Inv_Device equ 10 ;Invalid device name
323Init_Err_Ill_Device equ 11 ;Illegal device name
324Init_Err_Inv_Filename equ 12 ;Invalid filename
325
326;
327;******************************************************************************
328; FCB Structure
329;******************************************************************************
330;
331
332FCB STRUC
333Drive_Number db 0
334Filename_FCB db 8 dup(0)
335Extension db 3 dup(0)
336Current_Block dw 0
337Record_Size dw 0
338File_Size_Low_FCB dw 0
339File_Size_High_FCB dw 0
340File_Date_Time_FCB dw 0
341Reserved_FCB db 10 dup(0)
342Current_Record db 0
343Relative_Record_Low dw 0
344Relative_Record_High dw 0
345FCB ENDS
346
347
348;
349;******************************************************************************
350; Find First/Next DTA area
351;******************************************************************************
352;
353
354Find_DTA STRUC
355DTA_Reserved db 21 dup(0)
356DTA_Attribute db 0
357DTA_File_Time dw 0
358DTA_File_Date dw 0
359DTA_File_Size_Low dw 0
360DTA_File_Size_High dw 0
361DTA_Filename db 13 dup(0)
362Find_DTA ENDS
363
364
365
diff --git a/v4.0/src/CMD/XCOPY/MAKEFILE b/v4.0/src/CMD/XCOPY/MAKEFILE
new file mode 100644
index 0000000..d801f95
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/MAKEFILE
@@ -0,0 +1,49 @@
1#************************** makefile for cmd\... ***************************
2
3msg =..\..\messages
4dos =..\..\dos
5inc =..\..\inc
6hinc =..\..\h
7
8#
9####################### dependencies begin here. #########################
10#
11
12all: xcopy.exe
13
14xcopy.ctl: xcopy.skl \
15 $(msg)\$(COUNTRY).msg \
16 makefile
17
18xcopy.obj: xcopy.asm \
19 makefile \
20 $(inc)\versiona.inc \
21 $(inc)\copyrigh.inc \
22 $(inc)\sysmsg.inc \
23 $(inc)\msgserv.asm \
24 dos.equ \
25 xcopy.equ \
26 xcopy.ctl \
27 xcopy.cl1 \
28 xcopy.cl2 \
29 xcopy.cla \
30 xmainmsg.equ
31
32xcpyinit.obj: xcpyinit.asm \
33 makefile \
34 $(inc)\versiona.inc \
35 xcopy.equ \
36 dos.equ \
37 xinitmsg.equ
38
39xcopypar.obj: xcopypar.asm \
40 makefile \
41 $(inc)\psdata.inc \
42 $(inc)\parse.asm
43
44xcopy.exe: xcopy.obj \
45 makefile \
46 xcopy.lnk \
47 xcopypar.obj \
48 xcpyinit.obj
49 link @xcopy.lnk
diff --git a/v4.0/src/CMD/XCOPY/XCOPY.ASM b/v4.0/src/CMD/XCOPY/XCOPY.ASM
new file mode 100644
index 0000000..9a64f22
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/XCOPY.ASM
@@ -0,0 +1,3866 @@
1 PAGE, 132 ;
2TITLE XCOPY WITH FULL MEMORY USE - Ver. 4.00
3
4;****************** START OF SPECIFICATIONS *****************************
5; MODULE NAME: XCOPY
6;
7; DESCRIPTIVE NAME: selectively copy groups of files, which can include
8; lower level subdirectories.
9;
10; FUNCTION: The modules of XCOPY will be placed in the following order -
11; SSEG, DSEG(MAIN DATA, MAIN MSG), CSEG (MAIN + INIT),
12; DSEG_INIT(INIT DATA, INIT MSG)
13;
14; HEADER - informations needed about the file, subdirectory ...
15; Continue_Info -> 0 - a whole single file in this header
16; segment, or dir.
17; 1 - Continuation of a small file.
18; 2 - Continuation of a Big file
19; 3 - Eof of continuation
20; Next_Ptr -> points to the next header segment
21; Before_Ptr -> points to the old header segment
22;
23; By optionally using the Archive bit in the directory of each
24; file, XCOPY can be used as an alternative method of creating
25; backup files which can be accessed directly by DOS and its
26; applications without the need to "restore" the backup files.
27;
28; XCOPY is especially useful when several files are being copied
29; and there is a generous amount of RAM available, because XCOPY
30; will fill the memory with all the source files it can read in
31; before starting to create output files. If the memory is not
32; enough to hold all the source, this cycle will be repeated until
33; the process is completed. For single drive systems, this maximum
34; usage of the memory greatly reduces the amount of diskette
35; swapping that would be required by the usual COPY command.
36;
37; ENTRY POINT: MAIN
38;
39; INPUT: (DOS COMMAND LINE PARAMETERS)
40;
41; SOURCE OPERAND: TARGET OPERAND:
42;
43; [d:] [path] filename[.ext] [d:] [path] [filename[.ext]]
44; or
45; [d:] path [filename[.ext]]
46; or
47; d: [path] [filename[.ext]]
48;
49;
50; SWITCHES:
51;
52; /A /D /E /M /P /S /V /W
53;
54;The /A switch will copy only those files whose archive bit of the attribute is
55;set to one. The attribute of the source file is not changed. This option is
56;useful when making multiple backups when doing the non-final backup.
57;The archive bit is one when a file has be created or Revised since the last
58;time the bit was turned off. XCOPY /M or BACKUP /M will turn this bit off.
59;The ATTRIB command can also be used to change the setting of the archive bit.
60;
61;The /D switch will copy only those files whose date is the same or later than
62;the date specified. Depending on the country code you selected using the
63;COUNTRY command, the date is specified in the format corresponding to the
64;indicated country.
65;
66;The /E switch will create subdirectories on the target even if they end up
67;being empty after all copying is over. If /E is not specified, empty
68;subdirectories are not created.
69;
70;The /M switch will copy only those files whose archive bit is set in its
71;attribute. Unlike the /A switch, /M will cause the archive bit in the source
72;file to be turned off. This allows XCOPY to be used in making a final backup.
73;The archive bit is one when a file has be created or Revised since the last
74;time the bit was turned off. XCOPY /M or BACKUP /M will turn this bit off.
75;The ATTRIB command can also be used to change the setting of the archive bit.
76;
77;The /P switch will prompt the operator before copying each file. In this
78;situation, each file is copied onto the target before reading in the next
79;file. The multi-file copy into a large memory buffer is not done. The prompt
80;displays the complete filespec it proposes to copy and asks for (Y/N)
81;response, which is then read in from the standard input device.
82;
83;The /S switch will not only copy the files in the current source directory but
84;also those in all the subdirectories below the current one, with XCOPY
85;following the Tree of the subdirectories to access these files. /S does not
86;create an empty subdirectory on the target (unless /E is also specified).
87;If the /S switch is not specified, XCOPY works only within the specified (or
88;current) subdirectory of the source.
89;
90;The /V switch will cause DOS to verify that the sectors written on the target
91;are recorded properly. This option has been provided so you can verify that
92;critical data has been correctly recorded. This option will cause XCOPY to
93;run more slowly, due to the additional overhead of verification.
94;
95;The /W switch will instruct XCOPY to pause before actually starting the
96;movement of data, thus permit the copying of diskettes that do not actually
97;have XCOPY available on them. The diskette containing XCOPY can be mounted
98;first, the XCOPY command given with the /W option, then when the prompt
99;requesting permission to continue is given, that diskette can then be removed
100;and the source diskette mounted in its place, then the operator can press any
101;key to continue after the pause. This feature is especially useful in a
102;non-hardfile system.
103;
104; EXIT-NORMAL: ERRORLEVEL_0 - This is the normal completion code.
105; ERRORLEVEL_2 - This is due to termination via Control-Break.
106; ERRORLEVEL_4 - This is used to indicate an error condition.
107;
108; There are many types of problems that are detected and result in this
109; return code, such as:
110;
111; write failure due to hard disk error
112; disk full
113; conflict between name of new subdirectory and existing filename
114; access denied
115; too many open files
116; sharing violation
117; lock violation
118; general failure
119; file not found
120; path not found
121; directory full
122; invalid parms
123; reserved file name as source
124; insufficient memory
125; incorrect DOS version
126;
127;
128; INTERNAL REFERENCES:
129;
130; ROUTINES:
131;
132;
133; DATA AREAS:
134;
135;
136; EXTERNAL REFERENCES:
137;
138; ROUTINES:
139;
140;
141; DATA AREAS:
142;
143;
144; NOTES: This module should be processed with the SALUT pre-processor
145; with the re-alignment not requested, as:
146;
147; SALUT XCOPY,NUL,;
148;
149; To assemble these modules, the sequential
150; ordering of segments may be used.
151;
152; For LINK instructions:
153; link profile ..\lib
154;
155; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
156; Remove the BELL char.,turn off APPEND during TREE
157; search,Extended Attribute processing, Uppercasing
158; and "Out Of Space" during write to standard out.
159; A001 PTM0011 XCOPY not handling path >63 characters.
160; CHK_MAX_LENGTH proc(XCPYINIT) is Revised to err if
161; >63 chrs.
162; A002 PTM0012 XCOPY unnecessarily accessing current drive.
163; ORG_S_T_DEF is Revised to ignore CHDIR if drive
164; is not TARGET or SOURCE.
165; A003 PTM0088 XCOPY (\) missing in 'FILE SHARING ERROR'.
166; This problem is fixed with incorporation of the
167; new message services.
168; A004 PTM0700 9/02/87 Avoid duplicate switches and
169; display parm in error.
170; A005 DCR0201 9/11/87 Incorperate new format for EXTENDED
171; ATTRIBUTES.
172; A006 PTM1490 10/04/87 XCOPY /D CAUSES "INVALID PARAMETER"
173; MSG AND SHOULD BE "INVALID NUMBER OF PARAMETERS" ALSO
174; DATE IS NOT VALIDATED.
175; A007 PTM1657 10/14/87 XCOPY INVALIDLY FAILS TO READ A READ
176; ONLY FILE, AND OUTPUTS THE WRONG MSG.
177; A008 PTM1688 10/15/87 XCOPY NOT CREATING EMPTY SUBDIRS IF
178; THE SOURCE DIR. IS EMPTY.
179; A009 PTM2199 11/02/87 XCOPY NOT HANDELING FILENAMES GREATER
180; THAN 12 CHARACTERS.
181; A010 PTM2203 11/03/87 XCOPY NOT HANDELING DBCS PATH NAMES
182; PROPERLY. (INCORP. CHK. IF 1st BYTE IS DBCS)
183; A011 PTM2271 11/04/87 XCOPY NOT HANDELING FILENAMES GREATER
184; THAN 12 CHARACTERS.(S_FILE BUFFER OVERFLOWES).
185; A012 PTM2347 11/09/87 XCOPY SETTING THE CODE PAGE OF A DEV.
186; AND A DEV. IS NOT ALLOWED FOR A TARGET.
187; A013 PTM2565 11/17/87 XCOPY HANGS AUTOTEST. SET EXTENDED
188; ATTRIBUTE CALL TO DOS POINTS TO INVALID BUFFER.
189; A014 PTM2597 11/20/87 XCOPY REPORTS FILE CREATION ERROR
190; IF TARGET FILE IS GREATER THAN 12 CHARACTERS.
191; A015 PTM2782 12/04/87 XCOPY FILENAME (EXTENSION)
192; TRUNCATION ERROR. INCREASE HEADER BUFFER TO 3 PARA.
193; A016 PTM2783 12/09/87 XCOPY ALLOWS 'ASSIGN' DRIVES TO
194; BE COPIED ONTO THEMSELVS. ADD NEW CODE TO INIT.
195; A017 PTM3139 01/15/88 XCOPY HANGS WHEN TRYING TO OUTPUT
196; "INSUFFICIENT DISK SPACE" FOR MAKE DIRECTORY.
197; A018 PTM3283 02/01/88 XCOPY NEEDS TO CHANGE 'FILE NOT
198; FOUND' MSG TO EXTENDED ERROR MSG FORMAT. ALSO
199; DELETED DEF 28 IN XCOPY.SKL & XMAINMSG.EQU
200; A019 PTM3395 02/08/88 XCOPY FAILING TO SUSPEND THE
201; 'APPEND /X' FUNCTION. FIX IN XCOPY.SAL, XCOPY.EQU,
202; AND DOS.EQU.
203; A020 PTM3344 02/09/88 XCOPY READING PAST TOP_OF_MEMORY,
204; OVER-WRITING VIDIO BUFFER SET BY MODE 13H ON PS2s.
205; A021 PTM3513 02/19/88 XCOPY READING PAST TOP_OF_MEMORY,
206; OVER-WRITING VIDIO BUFFER SET BY MODE 13H ON PS2s.
207; A022 PTM3933 03/18/88 XCOPY NOT RESTORING DIRECTORY OF
208; DEFAULT DRIVE. FIX IN XCOPY.SAL.
209; A023 PTM3904 03/18/88 XCOPY NOT USING PARSE 03 MSG. FOR
210; 'INVALID SWITCH'. FIX IN XCOPY.SKL & XCPYINIT.SAL.
211; A024 PTM3958 03/22/88 XCOPY MSGS DO NOT CONFORM TO SPEC.
212; NEED NULL DELIMITER IN XCPYINIT.SAL.
213; A025 PTM3965 03/23/88 XCOPY LEAVING CURRENT TARGET DIR.
214; CHANGED. FIX IN XCPYINIT.SAL.
215; A026 PTM4920 05/19/88 XCOPY NOT OVERLAYING FILES ON FULL
216; TARGET DISK. FIX IN XCOPY.SAL.
217; A027 PTM5022 06/03/88 'PATH TOO LONG' MSG. WITH TWO CHAR.
218; SOURCE SUBDIR. FILESPEC. FIX IN XCPYINIT.SAL.
219;
220; Label: "The DOS XCOPY Utility"
221; "Version 4.00 (C) Copyright 1988 Microsoft"
222; "Licensed Material - Program Property of Microsoft"
223;
224;****************** END OF SPECIFICATIONS *****************************
225
226;--------------------------------
227; Include Files
228;--------------------------------
229INCLUDE XMAINMSG.EQU ;AN000;message file
230INCLUDE DOS.EQU ;AN000;
231INCLUDE XCOPY.EQU ;AN000;
232
233INCLUDE SYSMSG.INC ;AN000;
234
235MSG_UTILNAME <XCOPY> ;AN000;
236
237;-------------------------------
238; Structures
239;-------------------------------
240;HEADER - informations needed about the file, subdirectory ...
241;Continue_Info -> 0 - a whole single file in this header segment, or dir.
242; 1 - Continuation of a small file.
243; 2 - Continuation of a Big file
244; 3 - EOF of continuation
245;Next_Ptr -> points to the next header segment
246;Before_Ptr -> points to the old header segment
247
248HEADER STRUC
249 CONTINUE_INFO DB 0 ;set for filesize bigger then 0FFD0h
250 NEXT_PTR DW ? ;next buffer ptr in para
251 BEFORE_PTR DW ? ;before ptr in para
252 DIR_DEPTH DB ? ;same as S_DEPTH
253 CX_BYTES DW 0 ;actual # of bytes in this buffer seg.
254 ATTR_FOUND DB ? ;attribute found
255 FILE_TIME_FOUND DW ?
256 FILE_DATE_FOUND DW ?
257 LOW_SIZE_FOUND DW ?
258 HIGH_SIZE_FOUND DW ?
259 TARGET_DRV_LET DB " :" ;used for writing
260 FILENAME_FOUND DB 13 DUP (0) ;AC015; FILENAME
261 TERMINATE_STRING DB 16 DUP (0) ;AC015;TERM FILENAME STRING FOR DOS
262 ATTRIB_LIST DW ? ;AC005;EXTENDED ATTRIBUTE BUFFER
263;-------------------------------------------------------------------
264; extended attribute list used by extended open & get extended
265;-------------------------------------------------------------------
266; ATTRIB_LIST LABEL BYTE extended attribute buffer
267;
268;EA STRUC ; EXTENDED ATTRIBUTE
269;EA_TYPE DB ? ; TYPE
270;EAISUNDEF EQU 0 ; UNDEFINED TYPE (ATTRIB SKIPS)
271; ; (OR TYPE NOT APPLICABLE)
272; ; LENGTH: 0 TO 64K-1 BYTES
273;EAISLOGICAL EQU 1 ; LOGICAL (0 OR 1) (ATTRIB DISPLAYS) ; LENGTH: 1 BYTE
274;EAISBINARY EQU 2 ; BINARY INTEGER (ATTRIB DISPLAYS)
275; ; LENGTH: 1, 2, 4 BYTES
276;EAISASCII EQU 3 ; ASCII TYPE (ATTRIB DISPLAYS)
277; ; LENGTH: 0 TO 128 BYTES
278;EAISDATE EQU 4 ; DOS FILE DATE FORMAT (ATTRIB DISPLAYS)
279; ; LENGTH: 2 BYTES
280;EAISTIME EQU 5 ; DOS FILE TIME FORMAT (ATTRIB DISPLAYS)
281; ; LENGTH: 2 BYTES
282; ; OTHER VALUES RESERVED
283;EA_FLAGS DW ? ; FLAGS
284;EASYSTEM EQU 8000H ; EA IS SYSTEM DEFINED
285; ; (BUILTIN, NOT APPLICATION DEFINED)
286;EAREADONLY EQU 4000H ; EA IS READ ONLY (CANT BE CHANGED)
287;EAHIDDEN EQU 2000H ; EA IS HIDDEN FROM ATTRIB
288;EACREATEONLY EQU 1000H ; EA IS SETABLE ONLY AT CREATE TIME
289; ; OTHER BITS RESERVED
290;EA_RC DB ? ; FAILURE REASON CODE (SET BY DOS)
291;EARCNOTFOUND EQU 1 ; NAME NOT FOUND
292;EARCNOSPACE EQU 2 ; NO SPACE TO HOLD NAME OR VALUE
293;EARCNOTNOW EQU 3 ; NAME CAN'T BE SET ON THIS FUNCTION
294;EARCNOTEVER EQU 4 ; NAME CAN'T BE SET
295;EARCUNDEF EQU 5 ; NAME KNOWN TO THIS FS BUT NOT SUPPORTED
296;EARCDEFBAD EQU 6 ; EA DEFINTION BAD (TYPE, LENGTH, ETC)
297;EARCACCESS EQU 7 ; EA ACCESS DENIED
298;EARCUNKNOWN EQU -1 ; UNDETERMINED CAUSE
299;EA_NAMELEN DB ? ; LENGTH OF NAME
300;EA_VALLEN DW ? ; LENGTH OF VALUE
301;EA_NAME DB ? ; FIRST BYTE OF NAME
302;
303;EA_VALUE DB ? ; FIRST BYTE OF VALUE
304;
305HEADER ENDS
306
307SUB_LIST STRUC
308 DB 11 ;AN000;
309 DB 0 ;AN000;
310DATA_OFF DW 0 ;AN000; offset of data to be inserted
311DATA_SEG DW 0 ;AN000; offset of data to be inserted
312MSG_ID DB 0 ;AN000; n of %n
313FLAGS DB 0 ;AN000; Flags
314MAX_WIDTH DB 0 ;AN000; Maximum field width
315MIN_WIDTH DB 0 ;AN000; Minimum field width
316PAD_CHAR DB 0 ;AN000; character for pad field
317
318SUB_LIST ENDS
319
320
321
322
323;******************************************************************************
324SSEG SEGMENT PARA STACK
325 DB 64 DUP ('STACK ') ;256 words
326SSEG ENDS
327
328
329
330;******************************************************************************
331DGROUP GROUP DSEG,DSEG_INIT ;FOR CONVENIENT ADDRESSIBLITY OF
332 ;DSEG_INIT in INIT routine
333;******************************************************************************
334DSEG SEGMENT PARA PUBLIC ; DATA Segment
335;--- EXTERNAL VARIABLES ---
336EXTRN PARM_FLAG: BYTE
337EXTRN COMMAND_LINE: BYTE ;AN000;THE COMMAND LINE FOR THE PARSER
338;--- PUBLIC VARIABLES ---
339PUBLIC ERRORLEVEL
340
341PUBLIC DISP_S_PATH
342PUBLIC DISP_T_PATH
343PUBLIC S_DRV
344PUBLIC S_DRV_1
345PUBLIC T_DRV
346PUBLIC T_DRV_1
347PUBLIC T_DRV_2
348PUBLIC S_DRV_PATH
349PUBLIC S_PATH
350PUBLIC T_DRV_PATH
351PUBLIC T_PATH
352PUBLIC S_FILE
353PUBLIC T_FILENAME
354PUBLIC T_TEMPLATE
355PUBLIC T_MKDIR_LVL
356PUBLIC S_ARC_DRV
357PUBLIC S_ARC_PATH
358;
359PUBLIC PSP_SEG
360PUBLIC SAV_DEFAULT_DRV
361PUBLIC SAV_DEFAULT_DIR
362PUBLIC SAV_S_DRV
363PUBLIC SAV_S_CURDIR
364PUBLIC SAV_T_DRV
365PUBLIC SAV_T_CURDIR
366PUBLIC S_DRV_NUMBER
367PUBLIC T_DRV_NUMBER
368PUBLIC TOP_OF_MEMORY
369PUBLIC BUFFER_PTR
370PUBLIC BUFFER_BASE
371PUBLIC BUFFER_LEFT
372PUBLIC MAX_BUFFER_SIZE
373PUBLIC MAX_CX
374;
375PUBLIC MY_FLAG
376PUBLIC SYS_FLAG
377PUBLIC COPY_STATUS
378PUBLIC OPTION_FLAG
379PUBLIC INPUT_DATE
380PUBLIC INPUT_TIME
381
382PUBLIC SUBST_COUNT ;AN000;
383PUBLIC MSG_CLASS ;AN000;
384PUBLIC INPUT_FLAG ;AN000;
385PUBLIC MSG_NUM ;AN000;
386
387PUBLIC SUBLIST1 ;AN000;MSG SUBLIST USED BY INIT
388
389
390;--- VARIABLES DEFINED ---
391
392 MSG_SERVICES <MSGDATA> ;AN000;
393
394ERRORLEVEL DB 0 ;errorlevel
395INPUT_DATE DW 0
396INPUT_TIME DW 0
397PSP_SEG DW ?
398SAV_DEFAULT_DRV DB ? ;1 = A, 2 = B etc. saved default
399SAV_DEF_DIR_ROOT DB '\'
400SAV_DEFAULT_DIR DB 80 DUP (0)
401SAV_S_DRV DB 'A:\'
402SAV_S_CURDIR DB 80 DUP (0)
403SAV_T_DRV DB 'B:\'
404SAV_T_CURDIR DB 80 DUP (0)
405;
406
407DISP_S_PATH DB 67 DUP (0) ;mirror image of source path. used for display message when copying
408DISP_S_FILE DB 13 DUP (0)
409DISP_T_PATH DB 67 DUP (0) ;mirror image of target path
410DISP_T_FILE DB 13 DUP (0)
411;
412B_SLASH DB '\',0 ;AN000;
413
414
415FILE_COUNT LABEL WORD ;AN000;
416FILE_CNT_LOW DW 0 ;copied file count
417FILE_CNT_HIGH DW 0
418;
419
420;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
421APPENDFLAG DW 0 ;AN000;append /X status save area
422FOUND_FILE_FLAG DB 0 ;used for showing the message "File not found"
423;
424S_DRV_NUMBER DB 0 ;source, target drv #
425T_DRV_NUMBER DB 0
426;
427S_DRV_PATH LABEL BYTE ;source drv, path used for single_drv_copy
428S_DRV DB 'A:\'
429S_PATH DB 80 DUP (0) ;AN000;Initialized by calling GET CUR DIR
430S_DEPTH DB 0
431S_DRV_1 DB 'A:'
432S_FILE DB '????????.???',0 ;default filename to find file
433S_FILE_OVERFLO DB 20 DUP (0) ;AN011;BUFFER IF MORE THAN 12 CHARS.
434S_DIR DB '????????.???',0 ;to find any subdirectory name
435S_DIR_OVERFLO DB 20 DUP (0) ;AN011;BUFFER IF MORE THAN 12 CHARS.
436
437S_PARENT DB '..',0 ;source parent used for non single_drv_copy
438S_HANDLE DW 0 ;file handle opened
439
440S_ARC_DRV_PATH LABEL BYTE ;informations used to change source file's
441S_ARC_DRV DB 'A:\' ;archieve bits.
442S_ARC_PATH DB 64 DUP (0)
443S_ARC_DEPTH DB 0
444
445T_DRV_PATH LABEL BYTE ;target drv, path used all the time
446T_DRV DB 'B:\'
447T_PATH DB 80 DUP (0) ;AC016;init by call GET CUR DIR in INIT
448T_DEPTH DB 0
449T_FILE LABEL BYTE ;target filename for file creation
450T_DRV_1 DB 'B:' ;target drv letter
451T_FILENAME DB 15 DUP (0) ;target filename
452T_TEMPLATE DB 15 DUP (0) ;if global chr entered, this will be used instead of filename.
453
454T_PARENT LABEL BYTE
455T_DRV_2 DB 'B:'
456T_PARENT_1 DB '..',0
457T_HANDLE DW 0 ;target handle created
458T_MKDIR_LVL DB 0 ;# of target starting directories created.
459;
460;------------------------------------------
461; PRINT_STDOUT input parameter save area
462;------------------------------------------
463SUBST_COUNT DW 0 ;AN000; message substitution count
464MSG_CLASS DB 0 ;AN000; message class
465INPUT_FLAG DB 0 ;AN000; Type of INT 21 used for KBD input
466MSG_NUM DW 0 ;AN000; message number
467
468
469INPUT_BUFF db 20 dup(0) ;AN000; keyboard input buffer used
470 ;for user response (Y/N)
471
472;--------------------------------------------------------------
473; Following three sublists are used by the Message Retriever
474;--------------------------------------------------------------
475SUBLIST1 LABEL DWORD ;AN000;SUBSTITUTE LIST 1
476 DB 11 ;AN000;sublist size
477 DB 0 ;AN000;reserved
478 DD 0 ;AN000;substition data Offset
479 DB 1 ;AN000;n of %n
480 DB 0 ;AN000;data type
481 DB 0 ;AN000;maximum field width
482 DB 0 ;AN000;minimum field width
483 DB 0 ;AN000;characters for Pad field
484
485
486SUBLIST2 LABEL DWORD ;AN000;SUBSTITUTE LIST 2
487 DB 11 ;AN000;sublist size
488 DB 0 ;AN000;reserved
489 DD 0 ;AN000;substition data Offset
490 DB 2 ;AN000;n of %n
491 DB 0 ;AN000;data type
492 DB 0 ;AN000;maximum field width
493 DB 0 ;AN000;minimum field width
494 DB 0 ;AN000;characters for Pad field
495
496
497SUBLIST3 LABEL DWORD ;AN000;SUBSTITUTE LIST 3
498 DB 11 ;AN000;sublist size
499 DB 0 ;AN000;reserved
500 DD 0 ;AN000;substition data Offset
501 DB 3 ;AN000;n of %n
502 DB 0 ;AN000;data type
503 DB 0 ;AN000;maximum field width
504 DB 0 ;AN000;minimum field width
505 DB 0 ;AN000;characters for Pad field
506
507
508FILE_SEARCH_ATTR DW NORM_ATTR
509DIR_SEARCH_ATTR DW INCL_H_S_DIR_ATTR
510;
511OPEN_MODE DB Read_Only_Deny_Write ;READ_ONLY_DENY_WRITE ;access, sharing mode
512;
513;Equates are defined in XCOPY.EQU
514
515MY_FLAG DB 0 ;informations for a tree walk
516; find_first_flag equ 01h ;set MY_FLAG by "OR"
517; findfile_flag equ 02h
518; no_more_file equ 04h
519; single_copy_flag equ 08h ;single copy instead of multi copy
520; visit_parent_flag equ 10h ;visit parent node
521; found_flag equ 20h ;found flag - for find subdir
522; missing_link_flag equ 40h ;insuffiecient info. for not creating empty dir
523; is_source_flag equ 80h ;if set, dealing with source
524; reset_find_first equ 0FEh ;reset by AND
525; reset_findfile equ 0FDh
526; reset_no_more equ 0FBh
527; reset_visit_parent equ 0EFh
528; reset_found equ 0DFh
529; reset_missing_link equ 0BFh
530; reset_is_source equ 07Fh
531
532FILE_FLAG DB 0
533; cont_flag equ 01h
534; eof_flag equ 02h
535; big_file_flag equ 04h
536; file_bigger_flag equ 08h
537; created_flag equ 10h
538; reset_cont equ 0FEh
539; reset_eof equ 0FDh
540; reset_big_file equ 0FBh
541; reset_file_bigger equ 0F7h
542; reset_created equ 0EFh
543; reset_readfile equ 0F0h ;reset FILE_FLAG for read a file
544;
545COPY_STATUS DB 0
546; open_error_flag equ 01h
547; read_error_flag equ 02h
548; create_error_flag equ 04h
549; write_error_flag equ 08h
550; mkdir_error_flag equ 10h
551; chdir_error_flag equ 20h
552; maybe_itself_flag equ 40h
553; disk_full_flag equ 80h
554; reset_open_error equ 0FEh
555; reset_read_error equ 0FDh
556; reset_create_error equ 0FBh
557; reset_write_error equ 0F7h
558; reset_close_error equ 0EFh
559; reset_chdir_error equ 0DFh
560;
561ACTION_FLAG DB 0
562; reading_flag equ 01h ;display "Reading source files..."
563; reset_reading equ 0FEh ;do not display.
564;
565SYS_FLAG DB 0 ;system information
566; one_disk_copy_flag equ 01h ;xcopy with only one logical drive.
567; default_drv_set_flag equ 02h ;default drive has been changed by this program
568; default_s_dir_flag equ 04h ;source current directory saved.
569; default_t_dir_flag equ 08h ;target current directory saved.
570; removalble_drv_flag equ 10h
571; sharing_source_flag equ 20h ;source shared
572; sharing_target_flag equ 40h
573; turn_verify_off_flag equ 80h ;turn the verify off when exit to dos
574; reset_default_s_dir equ 0FBh ;reset default_s_dir_flag
575;
576OPTION_FLAG DB 0
577; slash_a equ 01h ;soft archieve ?
578; slash_d equ 02h ;date?
579; slash_e equ 04h ;create empty dir?
580; slash_m equ 08h ;hard archieve ? (turn off source archieve bit)
581; slash_p equ 10h ;prompt?
582; slash_s equ 20h ;walk the tree?
583; slash_v equ 40h ;verify on?
584; slash_w equ 80h ;show "Press any key to begin copying" msg)
585; reset_slash_a equ 0FEh ;turn off soft archieve
586; reset_slash_m equ 0F7h ;turn off hard archieve
587
588MAX_CX DW 0 ;less than 0FFD0h
589ACT_BYTES DW 0 ;actual bytes read.
590HIGH_FILE_SIZE DW 0
591LOW_FILE_SIZE DW 0
592;
593TOP_OF_MEMORY DW 0 ;para
594BUFFER_BASE DW 0 ;para
595MAX_BUFFER_SIZE DW 0 ;para. BUFFER_LEFT at INIT time.
596BUFFER_LEFT DW 0 ;para
597BUFFER_PTR DW 0 ;para. If buffer_left=0 then invalid value
598DATA_PTR DW 0 ;buffer_ptr + HEADER
599OLD_BUFFER_PTR DW 0 ;last buffer_ptr
600SIZ_OF_BUFF DW ? ;AN005;para. EXTENDED ATTRIB BUFF SIZE
601BYTS_OF_HDR DW ? ;AN005;bytes TOTAL HEADER SIZE
602PARA_OF_HDR DW 3 ;AC008;para. TOTAL HDR SIZE INIT TO 3
603OPEN_FILE_COUNT DW ? ;AN005;TRACKING OF OPEN FLS FOR BUFFER
604; ;SIZE CALCULATION.
605DBCSEV_OFF DW 0 ;AN010; remember where dbcs vector is
606DBCSEV_SEG DW 0 ;AN010;next time I don't have to look
607;
608;structured data storage allocation
609FILE_DTA Find_DTA <> ;DTA for find file
610DTAS Find_DTA 32 dup (<>) ;DTA STACK for find dir
611;** Througout the program BP will be used for referencing fieldsname in DTAS.
612;For example, DS:[BP].dta_filename.
613DSEG ENDS
614
615;******************************************************************************
616
617CSEG SEGMENT PUBLIC
618 ASSUME CS:CSEG, DS:DGROUP, SS:SSEG
619
620 MSG_SERVICES <LOADmsg,GETmsg,DISPLAYmsg,INPUTmsg,CHARmsg,NUMmsg> ;AN000;
621 MSG_SERVICES <XCOPY.CLA,XCOPY.CL1,XCOPY.CL2> ;AN000;
622
623
624
625
626;--- EXTERNAL PROCEDURES ---
627EXTRN INIT: NEAR ;INIT PROC
628;
629;--- PUBLIC PROCEDURES --- ;USED BY INIT
630PUBLIC SET_BUFFER_PTR
631PUBLIC STRING_LENGTH
632PUBLIC CONCAT_ASCIIZ
633PUBLIC LAST_DIR_OUT
634PUBLIC CHK_DRV_LETTER
635PUBLIC COMPRESS_FILENAME
636PUBLIC PRINT_STDOUT
637PUBLIC PRINT_STDERR
638PUBLIC SET_DEFAULT_DRV
639PUBLIC MAIN_EXIT
640PUBLIC MAIN_EXIT_A
641PUBLIC CTRL_BREAK_EXIT
642PUBLIC SWITCH_DS_ES
643PUBLIC MY_INT24
644
645;--- INT 24 ADDR ----------
646PUBLIC SAV_INT24_OFF
647PUBLIC SAV_INT24_SEG
648
649PUBLIC SYSLOADMSG ;AN000;
650PUBLIC SYSDISPMSG
651PUBLIC SYSGETMSG
652
653SAV_INT24 LABEL DWORD
654SAV_INT24_OFF DW 0 ;original int 24 addr holder
655SAV_INT24_SEG DW 0
656;--- START OF A PROGRAM ---
657 ASSUME DS:NOTHING ;AN000;
658 ASSUME ES:NOTHING ;AN000;
659MAIN PROC FAR
660 PUSH AX ;AN000;PRESERVE FOR INIT DRV VALIDITY
661 MOV BX,DGROUP
662 MOV ES,BX ;AN000;SET UP ADDRESS OF DSEG IN ES
663 ASSUME ES:DGROUP ;AN000;
664 MOV SI,81H ;AN000;POINT TO THE INPUT STRING
665 LEA DI,COMMAND_LINE ;AN000;POINT TO THE SAVE AREA IN PARSER
666 MOV CX,127 ;AN000;GET ALL THE DATA(LOOP COUNT)
667 REP MOVSB ;AN000;MOVE IT
668 MOV PSP_SEG,DS ;AN000;REMEMBER WHERE THE PSP IS
669 MOV DS,BX ;AN000;SET UP ADDRESS OF DSEG IN DS
670 ASSUME DS:DGROUP ;AN000;
671
672 CALL SYSLOADMSG ;AN000; preload all messages
673 jnc XCOPY_INIT ;AN000; no error, do xcopy init
674
675 CALL SYSDISPMSG ;AN000; else display error message
676 POP AX ;AN000;WAS PRESERVED FOR DRV VALIDATION
677 JMP JUST_EXIT ;AN000; exit
678
679XCOPY_INIT:
680 POP AX ;AN000;WAS PRESERVED FOR DRV VALIDATION
681 CALL INIT ;initialization
682 JC MAIN_EXIT ;error. (Already message has been displayed)
683 MOV BP, OFFSET DTAS ;initialize BP
684 OR ACTION_FLAG, READING_FLAG ;set reading flag for copy message
685
686;Before walking the tree, find out the /X status of APPEND and save it.
687;Then terminate the /X feature. After the tree search, restore the
688;original /X status. This is done at EXIT time.
689
690 MOV AX,CHK_APPEND ;AN000;CHECK IF APPEND INSTALLED
691 INT 2FH ;AN000;
692 OR AL,AL ;AN000;INSTALLED?
693; $IF NZ ;AN000;YES
694 JZ $$IF1
695 MOV AX,VER_APPEND ;AN019;ASK IF DOS VERSION OF APPEND
696 INT 2FH ;AN019;CALL THE FUNCTION
697 CMP AX,D_V_APPEND ;AN000;DOS VERSION?
698; $IF E ;AN000;YES
699 JNE $$IF2
700 MOV AX,GET_APPEND ;AN000;GET THE APPEND STATE
701 INT 2FH ;AN000;
702 MOV APPENDFLAG,BX ;AN000;SAVE THE STATE TO RESTORE
703 TEST APPENDFLAG,F_APPEND ;AN019;IS THE /X BIT ON?
704; $IF NZ ;AN000;YES
705 JZ $$IF3
706 MOV AX,SET_APPEND ;AN000;SET THE APPEND STATE
707 MOV BX,APPENDFLAG ;AN000;GET THE SAVED STATE
708 XOR BX,F_APPEND ;AN000;TURN OFF THE /X BIT
709 INT 2FH ;AN000;DO IT
710; $ENDIF ;AN000;
711$$IF3:
712; $ENDIF ;AN000;
713$$IF2:
714; $ENDIF ;AN000;
715$$IF1:
716
717 CALL TREE_COPY
718 CALL ORG_S_DEF ;restore the original source default dir
719 CALL WRITE_FROM_BUFFER ;write from buffer if we missed it.
720
721MAIN_EXIT:
722 MOV BX, DGROUP
723 MOV DS, BX ;re initialize ds, es
724 MOV ES, BX ;exit here if the status of source, target or default drv has been changed.
725 CALL CHK_FILE_NOT_FOUND ;if no files has been found, show the message.
726 ;
727; Set message substitution list
728 LEA SI,SUBLIST1 ;AN000; get addressability to sublist
729 LEA DX,FILE_COUNT ;AN000; offset to file count
730 MOV [SI].DATA_OFF,DX ;AN000; save data offset
731 MOV [SI].DATA_SEG,DS ;AN000; save data segment
732 MOV [SI].MSG_ID,1 ;AN000; message ID
733 MOV [SI].FLAGS,RIGHT_ALIGN+UNSGN_BIN_DWORD ;AN018;
734 MOV [SI].MAX_WIDTH,9 ;AN018; MAXIMUM FIELD WITH
735 MOV [SI].MIN_WIDTH,9 ;AN018; MINIMUM FIELD WITH
736 MOV [SI].PAD_CHAR,SPACE ;AN018; MINIMUM FIELD WITH
737
738; Set message parameters
739 MOV AX,MSG_FILES_COPIED ;AN000; message number
740 MOV MSG_NUM,AX ;AN000; set message number
741 MOV SUBST_COUNT,PARM_SUBST_ONE ;AN000; one message substitution
742 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
743 MOV INPUT_FLAG,NO_INPUT ;AN000; no user input
744 CALL PRINT_STDOUT ;AN000; display file count
745
746MAIN_EXIT_A:
747 MOV BX, DGROUP
748 MOV DS, BX ;re initialize ds, es
749 MOV ES, BX ;exit here if the status of source, target or default drv has been changed.
750 CALL CHK_MKDIR_LVL ;starting target directory has been created?
751 CALL ORG_S_T_DEF ;restore original target, source, default drv, and verify status
752
753JUST_EXIT: ;unconditional immediate exit
754
755; Restore the original status of APPEND if active.
756
757
758 MOV BX,APPENDFLAG ;AN000;GET THE STATUS WORD
759 OR BX,BX ;AN019;IF FLAGS SAVED, THIS IS DOS VER.
760; $IF NZ ;AN019;IF ACTIVE,
761 JZ $$IF7
762 MOV AX,SET_APPEND ;AN000;SET TO THE ORIGINAL STATE
763 INT 2FH ;AN000; turn on the /X feature
764; $ENDIF ;AN000;
765$$IF7:
766;
767 MOV AH, 4Ch ;return to dos
768 MOV AL, ERRORLEVEL ;set return code whatever
769 INT 21H
770CTRL_BREAK_EXIT:
771 MOV ERRORLEVEL, 2 ;set errorlevel to 2 for control break
772 JMP MAIN_EXIT_A
773
774MAIN ENDP
775;
776
777
778;----------------- SUBROUTINES ---------------------------------------------
779
780TREE_COPY PROC NEAR
781
782;Walk the source tree to read files and subdirectories
783
784 OR MY_FLAG, FINDFILE_FLAG ;deals with files
785 OR MY_FLAG, FIND_FIRST_FLAG ;find first
786 CALL SET_MY_DTA ;set DTA to FILE_DTA
787; $DO
788$$DO9:
789 CALL FIND_FILE ;find first (next)
790 TEST MY_FLAG, NO_MORE_FILE ;no more file?
791; $LEAVE NZ ;then exit loop
792 JNZ $$EN9
793 CALL READ_INTO_BUFFER ;else read the file into the buffer
794; $ENDDO
795 JMP SHORT $$DO9
796$$EN9:
797
798 TEST OPTION_FLAG, SLASH_S ;walk the tree?
799; $IF NZ,LONG
800 JNZ $$XL1
801 JMP $$IF12
802$$XL1:
803
804 AND MY_FLAG, RESET_FINDFILE ;now, deals with directory
805 OR MY_FLAG, FIND_FIRST_FLAG ;find first
806; $DO
807$$DO13:
808 CALL SET_MY_DTA ;set DTA to DTAS according to BP
809 CALL FIND_DIR ;find first (next)
810 TEST MY_FLAG, NO_MORE_FILE ;no more subdirectory?
811; $LEAVE NZ ;then leave this loop to return to caller
812 JNZ $$EN13
813 LEA DI, S_DRV_PATH
814 LEA SI, [BP].DTA_FILENAME
815 CMP S_PATH, 0 ;root directory?
816; $IF E
817 JNE $$IF15
818 MOV AL, 0FFh ;then '\' is already provided. Just concat.
819; $ELSE
820 JMP SHORT $$EN15
821$$IF15:
822 MOV AL, PATH_DELIM ;put delimiter
823; $ENDIF
824$$EN15:
825 CALL CONCAT_ASCIIZ ;make new path
826 test option_flag, slash_p ;prompt mode?
827; $IF NZ
828 JZ $$IF18
829 call p_concat_display_path
830; $ENDIF
831$$IF18:
832 INC S_DEPTH ;increase depth
833 CALL MAKE_HEADER ;make header in the buffer
834 OR MY_FLAG, IS_SOURCE_FLAG ;dealing with source
835 AND MY_FLAG, RESET_VISIT_PARENT ;going to visit child node
836 CALL CHANGE_S_DIR ;change source dir
837 ADD BP, type FIND_DTA ;increase DTAS stack pointer
838 CALL TREE_COPY ;tree copy the sub directory
839; $ENDDO
840 JMP SHORT $$DO13
841$$EN13:
842
843 CMP S_DEPTH, 0 ;starting directory? then exit
844; $IF NE ;else
845 JE $$IF21
846 DEC S_DEPTH ;dec depth
847 TEST OPTION_FLAG, SLASH_E ;copy subdirectories even if empty?
848; $IF Z
849 JNZ $$IF22
850 CALL DEL_EMPTY ;then check the old_buffer_ptr and
851 ;if it is a directory, then restore
852 ;buffer_ptr to old.
853; $ENDIF
854$$IF22:
855 LEA DI, S_DRV_PATH
856 CALL LAST_DIR_OUT ;change environments
857 test option_flag, slash_p ;prompt mode?
858; $IF NZ
859 JZ $$IF24
860 call p_cut_display_path
861; $ENDIF
862$$IF24:
863 LEA DX, S_DRV_PATH ;before returning to the caller
864 OR MY_FLAG, IS_SOURCE_FLAG
865 OR MY_FLAG, VISIT_PARENT_FLAG
866 CALL CHANGE_S_DIR
867 SUB BP, type FIND_DTA
868; $ENDIF
869$$IF21:
870; $ENDIF ;walk the tree
871$$IF12:
872 RET
873TREE_COPY ENDP
874;
875
876DEL_EMPTY PROC NEAR
877;If buffer is not full, and the tree walk is going to return to the parents,
878;this routine should be called.
879;If old_buffer_ptr points to a directory, then set buffer_ptr to this, and
880;increase buffer_left by HEADER (para) and set old_buffer_ptr to that of
881;BEFORE_PTR. i.e. delete the empty directory entry from the buffer.
882
883 PUSH ES
884
885 PUSH CS
886 POP AX
887 CMP OLD_BUFFER_PTR, AX ;buffer is empty?
888 JE DE_EXIT ;yes, exit
889
890 MOV ES, OLD_BUFFER_PTR
891 TEST ES:ATTR_FOUND, 10h ;directory?
892 JZ DE_EXIT ;if not, exit
893 MOV AX, OLD_BUFFER_PTR
894 MOV BUFFER_PTR, AX ;set new BUFFER_PTR
895 MOV AX, ES:BEFORE_PTR
896 MOV OLD_BUFFER_PTR, AX ;set new OLD_BUFFER_PTR
897 MOV AX, PARA_OF_HDR ;AN005;GET THE HEADER SIZE (para.)
898 ADD BUFFER_LEFT, AX ;AC005;dir entry must be only hdr SIZE.
899
900DE_EXIT:
901 POP ES
902 RET
903DEL_EMPTY ENDP
904;
905
906
907P_concat_display_path proc near
908;concatenate subdirectory name found from DTAS to the
909;DISP_S_PATH which will be used for prompts
910;DS - data seg
911 MOV DI, OFFSET DISP_S_PATH
912 LEA SI, [BP].DTA_FILENAME
913 CMP S_DEPTH, 0 ;this will be the first subdir?
914; $IF E
915 JNE $$IF28
916 MOV AL, 0FFh ;then do not put '\'
917; $ELSE
918 JMP SHORT $$EN28
919$$IF28:
920 MOV AL, Path_delim
921; $ENDIF
922$$EN28:
923 CALL CONCAT_ASCIIZ
924 RET
925P_concat_display_path endp
926;
927
928
929P_cut_display_path proc near
930;take the last dir out from the DISP_S_PATH for prompt.
931;DS,ES - data seg
932 MOV SI, OFFSET DISP_S_PATH
933 MOV DI, OFFSET DISP_S_PATH
934 CALL LAST_DIR_OUT
935; $IF C
936 JNC $$IF31
937 CALL CHK_DRV_LETTER
938; $IF NC
939 JC $$IF32
940 MOV BYTE PTR DS:[SI], 0
941; $ELSE
942 JMP SHORT $$EN32
943$$IF32:
944 MOV BYTE PTR [DI], 0
945; $ENDIF
946$$EN32:
947; $ELSE
948 JMP SHORT $$EN31
949$$IF31:
950 CMP S_DEPTH, 0
951; $IF E
952 JNE $$IF36
953 MOV DI, AX
954 DEC DI
955 MOV BYTE PTR [DI], '\'
956 MOV BYTE PTR [DI+1], 0
957; $ENDIF
958$$IF36:
959; $ENDIF
960$$EN31:
961 RET
962P_cut_display_path endp
963;
964
965
966READ_INTO_BUFFER PROC NEAR
967;Read *** a *** file into buffer
968 TEST MY_FLAG, SINGLE_COPY_FLAG ;single copy?
969; $IF Z,AND ;no, multi copy
970 JNZ $$IF39
971 TEST ACTION_FLAG, READING_FLAG ;show message?
972; $IF NZ ;yes.
973 JZ $$IF39
974 MOV AX,MSG_READING_SOURCE ;AN000; message number
975 MOV MSG_NUM,AX ;AN000; set message number
976 MOV SUBST_COUNT,NO_SUBST ;AN000; no message substitution
977 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
978 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
979 CALL PRINT_STDOUT ;AN000;show message "Reading source files"
980
981 AND ACTION_FLAG, RESET_READING ;reset it
982; $ENDIF
983$$IF39:
984
985 AND FILE_FLAG, RESET_READFILE ;reset file_flag to read a file
986 MOV AX,FILE_DTA.DTA_FILE_SIZE_HIGH
987 MOV HIGH_FILE_SIZE, AX
988 MOV AX,FILE_DTA.DTA_FILE_SIZE_LOW
989 MOV LOW_FILE_SIZE, AX
990 CALL CMP_FILESIZE_TO_BUFFER_LEFT ;compare sizes
991
992 MOV AX, PARA_OF_HDR ;AN005;GET THE HEADER SIZE (para.)
993 CMP MAX_BUFFER_SIZE, AX ;AN005;IS EA BUFFER TOO LARGE?
994; $IF B
995 JNB $$IF41
996 CLC ;AN005;CLEAR CARRY
997 MOV AX, MSG_INSUF_MEMORY ;AC005;GET THE MESSAGE ID
998 MOV MSG_NUM,AX ;AN005;NEED MESSAGE ID FOR PRINT
999 MOV SUBST_COUNT,NO_SUBST ;AN005;NO SUBSTITUTION TEXT
1000 MOV INPUT_FLAG,NO_INPUT ;AN005;NO INPUT = 0
1001 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN005;MESSAGE CLASS = -1
1002 CALL PRINT_STDERR ;AN005;print error. AX points to msg ID
1003; $ENDIF ;AN005;WE HAVE ENOUGH MEMORY
1004$$IF41:
1005 MOV AX, PARA_OF_HDR ;AN005;GET THE HEADER SIZE (para.)
1006 CMP MAX_BUFFER_SIZE,AX ;AN005;IS EA BUFFER TOO LARGE?
1007 JB RIB_ERROR ;AN005;CLOSE THE FILE AND GET THE NEXT
1008
1009 TEST FILE_FLAG, FILE_BIGGER_FLAG ;filesize > buffer_left - HEADER ?
1010 JZ RIB_SMALL ;if not, then small file
1011 MOV BX, S_HANDLE ;AN005;
1012 CALL CLOSE_A_FILE ;AN005;ONLY OPENED TO GET BUFFER SIZE
1013 CALL WRITE_FROM_BUFFER
1014 CALL CMP_FILESIZE_TO_BUFFER_LEFT ;compare again
1015 TEST FILE_FLAG, FILE_BIGGER_FLAG ;still bigger?
1016 JNZ RIB_BIG ;yes. Big file
1017RIB_SMALL:
1018 CALL SMALL_FILE
1019 JC RIB_ERROR
1020 JMP RIB_EXIT
1021RIB_BIG:
1022 MOV BX, S_HANDLE ;AN005;
1023 CALL CLOSE_A_FILE ;AN005;ONLY OPENED TO GET BUFFER SIZE
1024 CALL BIG_FILE
1025 JNC RIB_EXIT
1026RIB_ERROR:
1027 TEST COPY_STATUS, OPEN_ERROR_FLAG ;open error?
1028 JNZ RIB_EXIT ;just exit. find next file
1029 MOV BX, S_HANDLE ;else write error
1030 CALL CLOSE_A_FILE ;close the troubled file
1031 ;and find next file
1032RIB_EXIT:
1033 TEST MY_FLAG, SINGLE_COPY_FLAG ;single copy?
1034; $IF NZ
1035 JZ $$IF43
1036 CALL WRITE_FROM_BUFFER ;then write a file
1037; $ENDIF
1038$$IF43:
1039 RET
1040READ_INTO_BUFFER ENDP
1041;
1042
1043
1044SMALL_FILE PROC NEAR
1045;handles a file smaller than max_buffer_size or buffer_left, i.e. fit in memory.
1046;This routine will call MAKE_HEADER, SET_BUFFER_PTR< READ_A_FILE,
1047;CALC_FILE_SIZE, CMP_FILE_FFD0h, CLOSE_A_FILE.
1048
1049SMF_CONT:
1050 CALL CMP_FILE_FFD0h ;filesize > 0FFD0h ?
1051 TEST FILE_FLAG, FILE_BIGGER_FLAG
1052 JZ SMF_EOF ;filesize <= 0FFD0h
1053 OR FILE_FLAG, CONT_FLAG ;filesize > 0FFD0h. set cont_flag
1054 MOV CX, 0FFD0h ;# of bytes to read
1055 CALL READ_A_FILE
1056 JC SMF_ERROR ;unsuccessful read?
1057 CALL MAKE_HEADER ;else make header and ready for next
1058 CALL CALC_FILE_SIZE ;filesize = filesize - bytes read
1059 JMP SMF_CONT ;loop. compare again with the rest
1060
1061SMF_EOF:
1062 MOV CX, LOW_FILE_SIZE ;rest of the bytes to read
1063 OR FILE_FLAG, EOF_FLAG ;AN000;set EOF
1064 CALL READ_A_FILE
1065 JC SMF_ERROR
1066 CALL MAKE_HEADER
1067 MOV BX, S_HANDLE
1068 CALL CLOSE_A_FILE
1069 JMP SMF_EXIT
1070SMF_ERROR:
1071 ;
1072SMF_EXIT:
1073 RET
1074SMALL_FILE ENDP
1075;
1076
1077
1078BIG_FILE PROC NEAR
1079;handles a file which is bigger than max_buffer_size
1080;Needs 2 file handles open concurrently for read and write
1081
1082 OR FILE_FLAG, BIG_FILE_FLAG
1083 OR FILE_FLAG, CONT_FLAG
1084 CALL OPEN_A_FILE
1085 JC BIF_ERROR ;error in open?
1086 CMP MAX_BUFFER_SIZE, 0FFFh ;max buffer size > 0FFFh in para ?
1087 JA BIF_BIG ;yes. large buffer system
1088 ;else small buffer
1089 MOV CX, MAX_CX ;CX = max_buffer_size * 16 - HEADER
1090BIF_SM:
1091 CALL READ_A_FILE
1092 JC BIF_ERROR ;read error?
1093 CALL MAKE_HEADER
1094 CALL WRITE_FROM_BUFFER
1095 JC BIF_ERROR ;write error?
1096 TEST FILE_FLAG, EOF_FLAG ;end of file set by READ_A_FILE?
1097 JZ BIF_SM ;if not, read again
1098 MOV BX, S_HANDLE
1099 CALL CLOSE_A_FILE
1100 JMP BIF_EXIT ;finished.
1101BIF_BIG:
1102 MOV CX, 0FFD0h ;max # of data bytes this program supports
1103BIF_BIG1:
1104 CALL READ_A_FILE
1105 JC BIF_ERROR
1106 CALL MAKE_HEADER
1107 CALL CALC_FILE_SIZE ;modify file size
1108BIF_BIG2:
1109 CALL CMP_FILESIZE_TO_BUFFER_LEFT ;filesize > buffer_left?
1110 TEST FILE_FLAG, FILE_BIGGER_FLAG ;yes.
1111 JZ BIF_END ;if it is not, call small_file
1112 MOV AX, PARA_OF_HDR ;AN021;GET THE ATTR. HDR SIZE
1113 ADD AX, 0FFFh ;AN021;
1114 CMP BUFFER_LEFT, AX ;AC021;BUFFER_LEFT >= 0FFF0h+HDR SIZE?
1115 JAE BIF_BIG ;then loop again.
1116 MOV AX, PARA_OF_HDR ;AN021;GET THE ATTR. HDR SIZE
1117 ADD AX, 140H ;AN021;
1118 CMP BUFFER_LEFT, AX ;AC021;BUFFER_LEFT >= 5Kbytes+HDR SIZE?
1119 ;minimum buffer size this pgm supports.
1120 JL BIF_BIG3 ;then flush buffer and try again. **IF system buffer left < 5 K then infinit loop can happen.
1121 MOV AX,BUFFER_LEFT
1122 SUB AX,PARA_OF_HDR ;AC005;FOR HEADER SIZE para.
1123 MOV CX,16
1124 MUL CX ;AN020;MAKE IT NUMBER OF BYTES
1125 MOV CX,AX ;AN020;FOR READ
1126 JMP BIF_BIG1 ;read again
1127BIF_BIG3:
1128 CALL WRITE_FROM_BUFFER
1129 JC BIF_ERROR
1130 JMP BIF_BIG2 ;flush buffer and compare again.
1131BIF_END:
1132 CALL SMALL_FILE ;when filesize <= buffer_left then SMALL_FILE will finish it.
1133 JC BIF_ERROR ;something wrong?
1134 CALL WRITE_FROM_BUFFER ;else finish copying this file
1135 JNC BIF_EXIT
1136BIF_ERROR:
1137 ;what happened?
1138BIF_EXIT:
1139 RET
1140BIG_FILE ENDP
1141;
1142
1143
1144MAKE_HEADER PROC NEAR
1145;When called by READ_A_FILE after the data had been read into the buffer, this
1146;routine will put the header which is just below the data area where the
1147;current BUFFER_PTR points. The header E.A.BUFFER SIZE + (3 para) long. And
1148;this routine will also call SET_BUFFER_PTR to set the BUFFER_PTR, BUFFER_LEFT
1149;for the next process.
1150;If called by TREE_COPY for a SUBDIRECTORY handle, this routine should
1151;check the BUFFER_LEFT (when called by READ_A_FILE, the caller is assumed
1152;to check the size of buffer_left before calling.) In this case, this
1153;routine will set the next BUFFER_PTR, BUFFER_LEFT, OLD_BUFFER_PTR
1154;instead of SET_BUFFER_PTR routine.
1155;Informations are obtained from the DTA area (for file - FILE_DTA.xxx
1156;dir - DS:[BP].xxx ) and stored into the header by referencing ES:field;s name.
1157;DS - Program Data area
1158;ES - will be used for a header segment in the buffer.
1159;
1160 PUSH ES ;save ES
1161 PUSH AX
1162
1163MH_AGAIN:
1164 MOV AX,BUFFER_PTR ;buffer_ptr is a segment
1165 MOV ES, AX ;now, ES is a header seg.
1166;
1167
1168 MOV AX, PARA_OF_HDR ;AN005;GET THE HEADER SIZE (para.)
1169 CMP BUFFER_LEFT,AX ;AC005;buffer_left=less than NEEDED?
1170 JAE MH_START
1171 CALL WRITE_FROM_BUFFER ;if so, flush buffer
1172 JC MH_ERROR_BRIDGE ;write error?
1173 JMP SHORT MH_AGAIN ;reinitialize ES to new buffer ptr
1174MH_START:
1175 TEST MY_FLAG, FINDFILE_FLAG ;identify caller.
1176 JNZ MH_FILE ;if a file, jmp to MH_FILE
1177 ;else deals with directory.
1178 MOV ES:CONTINUE_INFO, 0 ;not a continuation.
1179 MOV AX,OLD_BUFFER_PTR
1180 MOV ES:BEFORE_PTR, AX ;set before_ptr in header
1181 MOV AX,BUFFER_PTR
1182 MOV OLD_BUFFER_PTR, AX ;set variable OLD_BUFFER_PTR
1183 ADD AX,PARA_OF_HDR ;AC005;AX = BUFFER_PTR+HEADER(para)
1184 MOV BUFFER_PTR, AX ;set new BUFFER_PTR
1185 MOV ES:NEXT_PTR, AX ;set NEXT_PTR in the header
1186 MOV AX, PARA_OF_HDR ;AN005;GET THE HEADER SIZE (para.)
1187 SUB BUFFER_LEFT,AX ;AC005;adjust BUFFER_LEFT
1188 CMP BUFFER_LEFT,AX ;AC005;less than HEADER SIZE (para) ?
1189; $IF B
1190 JNB $$IF45
1191 MOV BUFFER_LEFT, 0 ;indicate buffer_full
1192; $ENDIF
1193$$IF45:
1194 MOV AL, S_DEPTH
1195 MOV ES:DIR_DEPTH, AL ;now save other info's
1196 MOV AL, DS:[BP].DTA_ATTRIBUTE
1197 MOV ES:ATTR_FOUND, AL ;in this case, DIR
1198 MOV AL, BYTE PTR T_DRV
1199 MOV ES:TARGET_DRV_LET, AL ;mov target drive letter
1200 MOV ES:TARGET_DRV_LET+1, DRV_delim ; ':'
1201 MOV CX, 13
1202 LEA SI, [BP].DTA_FILENAME ;DS:SI
1203 MOV DI, OFFSET ES:FILENAME_FOUND ;ES:DI
1204 REP MOVSB ;mov sting until cx = 0
1205 JMP MH_EXIT
1206MH_ERROR_BRIDGE: JMP MH_ERROR
1207MH_FILE: ;handles a file header hereafter.
1208 TEST FILE_FLAG, CONT_FLAG ;continuation?
1209 JZ MH_WHOLE_FILE ;no, just a whole file
1210 TEST FILE_FLAG, EOF_FLAG ;Eof flag set?
1211 JNZ MH_CONT_END ;yes, must be end of continuation
1212 TEST FILE_FLAG, BIG_FILE_FLAG ;Is this a big file?
1213 JNZ MH_BIG ;yes
1214 MOV ES:CONTINUE_INFO, 1 ;else small file continuation.
1215 JMP MH_A_FILE
1216MH_WHOLE_FILE:
1217 MOV ES:CONTINUE_INFO, 0
1218 JMP MH_A_FILE
1219MH_CONT_END:
1220 MOV ES:CONTINUE_INFO, 3
1221 JMP MH_A_FILE
1222MH_BIG:
1223 MOV ES:CONTINUE_INFO, 2
1224MH_A_FILE:
1225 MOV AX,FILE_DTA.DTA_FILE_TIME
1226 MOV ES:FILE_TIME_FOUND, AX
1227 MOV AX, FILE_DTA.DTA_FILE_DATE
1228 MOV ES:FILE_DATE_FOUND, AX
1229 MOV AX, FILE_DTA.DTA_FILE_SIZE_LOW
1230 MOV ES:LOW_SIZE_FOUND, AX
1231 MOV AX, FILE_DTA.DTA_FILE_SIZE_HIGH
1232 MOV ES:HIGH_SIZE_FOUND, AX
1233 MOV AL, BYTE PTR T_DRV
1234 MOV ES:TARGET_DRV_LET, AL
1235 MOV ES:TARGET_DRV_LET+1, DRV_DELIM
1236 MOV CX, 13
1237 MOV SI, OFFSET FILE_DTA.DTA_FILENAME
1238 MOV DI, OFFSET ES:FILENAME_FOUND
1239 REP MOVSB
1240
1241; Get Extended Attribute list of the opened file and save in attribute buff.
1242
1243 MOV BX,S_HANDLE ;AN005; BX = handle
1244 MOV SI,ALL_ATTR ;AN005; SELECT ALL ATTRIBUTES SIZE
1245 MOV CL, PARAGRAPH ;AN005; PARAGRAPH = 4 FOR DIV BY 16
1246 MOV AX,SIZ_OF_BUFF ;AN005; GET THE SIZE EXPRESSED IN para.
1247 SHL AX, CL ;AN005; GET # OF BYTES FROM para.
1248 MOV CX, AX ;AN005; NEEDS TO BE IN CX
1249 MOV DI, OFFSET ES:ATTRIB_LIST ;AN005; ES:DI = E A LIST IN BUFFER
1250 MOV AX, GET_ATTRIB ;AN005; extended attribute code 5702H
1251 INT 21H ;AN005; get extended attribute list
1252
1253 JC MH_ERROR ;AN000; jump if error
1254
1255 MOV AX, OLD_BUFFER_PTR
1256 MOV ES:BEFORE_PTR, AX
1257 MOV AX, ACT_BYTES
1258 MOV ES:CX_BYTES, AX
1259 CALL SET_BUFFER_PTR ;set buffer_ptr for next. AX is already set.
1260 MOV AX, BUFFER_PTR
1261 MOV ES:NEXT_PTR, AX ;next buffer_ptr is next_ptr
1262 MOV AL, S_DEPTH
1263 MOV ES:DIR_DEPTH, AL ;same as source depth
1264 MOV AL, FILE_DTA.DTA_ATTRIBUTE
1265 MOV ES:ATTR_FOUND, AL ;attribute found
1266 JMP MH_EXIT ;AN000;
1267MH_ERROR:
1268 OR COPY_STATUS, OPEN_ERROR_FLAG ;AN000;
1269 CALL EXTENDED_ERROR_HANDLER ;AN000;
1270MH_EXIT:
1271 POP AX
1272 POP ES
1273 RET
1274MAKE_HEADER ENDP
1275;
1276
1277
1278OPEN_A_FILE PROC NEAR
1279
1280;-------------------------------------------------------------------------
1281; Use extended open DOS call to open source file,
1282; if successfully open, then save filehand to S_HANDLE.
1283; And update the open file count.
1284;-------------------------------------------------------------------------
1285
1286 LEA SI,FILE_DTA.DTA_FILENAME ;AN005; DS:SI-->NAME TO OPEN
1287 MOV DX,OPN_FLAG ;AN000; flag = 0101H
1288 MOV CX,OPN_ATTR ;AN000; attribute = 0
1289 MOV BX,OPN_MODE ;AN007; open mode = 0000H (READ)
1290 MOV DI, NUL_LIST ;AN005; ES:DI = -1
1291 MOV AX, Ext_Open ;AN000; = 6Ch
1292 INT 21H ;AN000; OPEN SOURCE FILE
1293
1294 JC OF_ERROR
1295 MOV S_HANDLE, AX ;save filehandle
1296 INC OPEN_FILE_COUNT ;AN005;UPDATE THE OPEN FILE COUNTER
1297
1298 JMP OF_EXIT ;AN000; exit
1299
1300OF_ERROR:
1301 OR COPY_STATUS, OPEN_ERROR_FLAG
1302 CALL EXTENDED_ERROR_HANDLER
1303OF_EXIT:
1304 RET
1305OPEN_A_FILE ENDP
1306;
1307
1308
1309CMP_FILE_FFD0h PROC NEAR
1310;check whether the filesize in HIGH_FILE_SIZE, LOW_FILE_SIZE is bigger than
1311;0FFD0h. If it is, then set FILE_BIGGER_FLAG, else reset it.
1312 CMP HIGH_FILE_SIZE, 0
1313; $IF E,AND
1314 JNE $$IF47
1315 CMP LOW_FILE_SIZE, 0FFD0h
1316; $IF BE
1317 JNBE $$IF47
1318 AND FILE_FLAG, RESET_FILE_BIGGER ;filesize <= 0FFD0h
1319; $ELSE
1320 JMP SHORT $$EN47
1321$$IF47:
1322 OR FILE_FLAG, FILE_BIGGER_FLAG
1323; $ENDIF
1324$$EN47:
1325 RET
1326CMP_FILE_FFD0h ENDP
1327;
1328
1329CALC_FILE_SIZE PROC NEAR
1330;subtract the bytes read (ACT_BYTES) from the filesize in HIGH_FILE_SIZE,
1331;LOW_FILE_SIZE.
1332 MOV AX, ACT_BYTES
1333 SUB LOW_FILE_SIZE, AX
1334 SBB HIGH_FILE_SIZE, 0
1335 RET
1336CALC_FILE_SIZE ENDP
1337;
1338
1339
1340READ_A_FILE PROC NEAR
1341;read a file.
1342;if after reading, AX < CX or AX = 0 the set EOF_FLAG.
1343;INPUT:CX - # of bytes to read
1344; BUFFER_PTR
1345; S_HANDLE
1346;OUTPUT: ACT_BYTES
1347
1348 PUSH DS ;save program data seg
1349 MOV AH, Read
1350 MOV BX, S_HANDLE
1351 MOV DX, BUFFER_PTR ;current buffer header seg
1352 ADD DX, PARA_OF_HDR ;AC005;skip the header part
1353 MOV DS, DX ;now DS = buffer_ptr + HDR, data area
1354 XOR DX, DX ;offset DX = 0
1355 INT 21H
1356 POP DS ;restore program data area
1357 JC RF_ERROR ;read error?
1358 CMP AX, CX
1359 JE RF_OK
1360 OR FILE_FLAG, EOF_FLAG ;EOF reached. AX = 0 or AX < CX
1361RF_OK:
1362 CLC ;clear carry caused from CMP
1363 MOV ACT_BYTES, AX ;save actual bytes read
1364 JMP RF_EXIT
1365RF_ERROR:
1366 OR COPY_STATUS, READ_ERROR_FLAG
1367 CALL EXTENDED_ERROR_HANDLER
1368RF_EXIT:
1369 RET
1370READ_A_FILE ENDP
1371;
1372
1373
1374FIND_IT PROC NEAR
1375;set first or next depending on FIND_FIRST_FLAG.
1376;once called, reset FIND_FIRST_FLAG.
1377 TEST MY_FLAG, FIND_FIRST_FLAG
1378; $IF NZ ;yes
1379 JZ $$IF50
1380 MOV AH, Find_First
1381; $ELSE
1382 JMP SHORT $$EN50
1383$$IF50:
1384 MOV AH, Find_Next
1385; $ENDIF
1386$$EN50:
1387 AND MY_FLAG, RESET_FIND_FIRST ;reset FIND_FIRST_FLAG
1388 INT 21H
1389 RET
1390FIND_IT ENDP
1391;
1392
1393
1394FIND_FILE PROC NEAR
1395;find a file
1396;set NO_MORE_FILE if carry.
1397; $SEARCH
1398$$DO53:
1399 TEST MY_FLAG, FIND_FIRST_FLAG ;find first ?
1400; $IF NZ
1401 JZ $$IF54
1402 MOV DX, OFFSET S_FILE
1403 MOV CX, File_Search_Attr ;normal = 0
1404; $ELSE
1405 JMP SHORT $$EN54
1406$$IF54:
1407 MOV DX, OFFSET FILE_DTA
1408; $ENDIF
1409$$EN54:
1410 CALL FIND_IT
1411; $EXITIF C
1412 JNC $$IF53
1413 OR MY_FLAG, NO_MORE_FILE ;no more file in this directory
1414; $ORELSE
1415 JMP SHORT $$SR53
1416$$IF53:
1417 MOV FOUND_FILE_FLAG, 1 ;set the flag for "File not found" msg.
1418 CALL FILTER_FILES ;found. filter it with options
1419 TEST MY_FLAG, FOUND_FLAG
1420; $ENDLOOP NZ ;if found, leave this loop else start again
1421 JZ $$DO53
1422 AND MY_FLAG, RESET_NO_MORE
1423; $ENDSRCH
1424$$SR53:
1425 RET
1426FIND_FILE ENDP
1427;
1428FIND_DIR PROC NEAR
1429;find directory entry
1430;set NO_MORE_FLAG if carry.
1431; $SEARCH
1432$$DO61:
1433 TEST MY_FLAG, FIND_FIRST_FLAG
1434; $IF NZ
1435 JZ $$IF62
1436 MOV DX, OFFSET S_DIR
1437 MOV CX, DIR_SEARCH_ATTR
1438; $ELSE
1439 JMP SHORT $$EN62
1440$$IF62:
1441 MOV DX, BP
1442; $ENDIF
1443$$EN62:
1444 CALL FIND_IT
1445; $EXITIF C ;no more file
1446 JNC $$IF61
1447 OR MY_FLAG, NO_MORE_FILE ;set MY_FLAG and exit this loop
1448; $ORELSE ;otherwise found a file
1449 JMP SHORT $$SR61
1450$$IF61:
1451 CMP DS:[BP].DTA_ATTRIBUTE, Is_subdirectory ; directory?
1452; $IF E,AND
1453 JNE $$IF67
1454 CMP DS:[BP].DTA_FILENAME, A_dot ;starts with . ?
1455; $IF NE ;if not, then desired subdir
1456 JE $$IF67
1457 OR MY_FLAG, FOUND_FLAG ;found
1458; $ELSE
1459 JMP SHORT $$EN67
1460$$IF67:
1461 AND MY_FLAG, RESET_FOUND
1462; $ENDIF
1463$$EN67:
1464 TEST MY_FLAG, FOUND_FLAG
1465; $ENDLOOP NZ ;if found, leave this loop else start again
1466 JZ $$DO61
1467 AND MY_FLAG, RESET_NO_MORE ;found. set my_flag and exit
1468; $ENDSRCH
1469$$SR61:
1470 RET
1471FIND_DIR ENDP
1472;
1473
1474
1475FILTER_FILES PROC NEAR
1476;FILE_DTA.XXX HAS INFORMATIONS
1477;this routine also show the prompt of source path, filename, if SLASH_P is on.
1478
1479 TEST OPTION_FLAG, SLASH_A ;soft archieve?
1480 JNZ SLASH_AM_RTN ;yes
1481 TEST OPTION_FLAG, SLASH_M ;then hard archieve?
1482 JNZ SLASH_AM_RTN ;yes
1483FF_D:
1484 TEST OPTION_FLAG, SLASH_D ;date?
1485 JNZ SLASH_D_RTN
1486FF_P:
1487 TEST OPTION_FLAG, SLASH_P ;prompt mode? ** this should be placed last.
1488 JNZ SLASH_P_RTN
1489 JMP SHORT FF_FOUND ;no more selective options. copy this file.
1490SLASH_AM_RTN: ;soft or hard archieve.
1491 CALL CHK_ARCHIEVE_BIT
1492 JC FF_NOT_FOUND
1493 JMP SHORT FF_D ;check other options
1494SLASH_D_RTN:
1495 CALL CHK_DATE_FILE ;check file's date
1496 JC FF_NOT_FOUND
1497 JMP SHORT FF_P
1498slash_p_rtn:
1499 call prompt_path_file ;show message and get input from the user
1500 jc ff_not_found ;user does not want this file
1501FF_FOUND:
1502 OR MY_FLAG, FOUND_FLAG ;set found_flag
1503 JMP SHORT FF_EXIT
1504FF_NOT_FOUND:
1505 AND MY_FLAG, RESET_FOUND ;this file is not what we want to copy
1506FF_EXIT:
1507 RET
1508FILTER_FILES ENDP
1509;
1510CHK_ARCHIEVE_BIT PROC NEAR
1511;check the current FILE.DTA area and if archieve bit is on, found.
1512 TEST FILE_DTA.DTA_ATTRIBUTE, 20h ;archieve on?
1513; $IF NZ ;yes
1514 JZ $$IF72
1515 CLC ;clear carry
1516; $ELSE
1517 JMP SHORT $$EN72
1518$$IF72:
1519 STC ;archieve bit is off. Don't
1520; $ENDIF ;have to copy this file
1521$$EN72:
1522 RET
1523CHK_ARCHIEVE_BIT ENDP
1524;
1525CHK_DATE_FILE PROC NEAR
1526;
1527 MOV CX, FILE_DTA.DTA_FILE_DATE
1528 CMP CX, INPUT_DATE ;FILE_DATE < INPUT_DATE
1529; $IF B
1530 JNB $$IF75
1531 STC ;not found
1532; $ELSE
1533 JMP SHORT $$EN75
1534$$IF75:
1535 CLC ;found desired file
1536; $ENDIF
1537$$EN75:
1538 RET
1539CHK_DATE_FILE ENDP
1540;
1541
1542
1543PROMPT_PATH_FILE PROC NEAR
1544
1545;show the current source path, filename found, and get the user input.
1546;if it is yes, then reset carry, no, set carry otherwise show
1547;the whole message again.
1548;DS, ES - data seg
1549
1550 MOV CX, 13 ;13 max
1551 LEA SI, FILE_DTA.DTA_FILENAME
1552 MOV DI, OFFSET DISP_S_FILE
1553 REP MOVSB ;filename => disp_s_file
1554PPF_AGAIN:
1555 LEA SI,SUBLIST1 ;AN000; get addressability to sublist
1556 LEA DX,DISP_S_PATH ;AN000; offset to PATH NAME
1557 MOV [SI].DATA_OFF,DX ;AN000; save offset
1558 MOV [SI].DATA_SEG,DS ;AN000; save data segment
1559 MOV [SI].MSG_ID,1 ;AN000; message ID
1560 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
1561 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
1562 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
1563
1564 LEA SI,SUBLIST2 ;AN000; get addressability to sublist
1565 LEA DX,DISP_S_FILE ;AN000; offset to FILE NAME
1566 MOV [SI].DATA_OFF,DX ;AN000; save offset
1567 MOV [SI].DATA_SEG,DS ;AN000; save data segment
1568 MOV [SI].MSG_ID,2 ;AN000; message ID
1569 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
1570 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
1571 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
1572 LEA SI,SUBLIST1 ;AN000;
1573
1574 CMP S_DEPTH,0 ;now dealing with starting dir?
1575 JE PATH_FILE_QUERY ;ask (Y/N)
1576 JMP PPF_1
1577
1578PATH_FILE_QUERY:
1579
1580 MOV AX,P_S_PATH_FILE0 ;no back slash, since it is already there
1581 JMP PPF_PRT ;AN000;
1582
1583PPF_1:
1584
1585 MOV AX,P_S_PATH_FILE1 ; Path and file name with
1586 ; back slash delemeter
1587PPF_PRT:
1588 MOV MSG_NUM,AX ;AN000; set message number
1589 MOV SUBST_COUNT,PARM_SUBST_TWO ;AN000; substitution count
1590 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
1591 MOV INPUT_FLAG,DOS_KEYB_INP ;AN000; Y or N INPUT
1592 CALL PRINT_STDOUT ;AN000; Display message
1593 PUSH AX ;AN000; SAVE IT
1594
1595 MOV AX,MSG_CR_LF_STR ;AN000; JUST CR,LF
1596 MOV MSG_NUM,AX ;AN000; set message number
1597 MOV SUBST_COUNT,NO_SUBST ;AN000; substitution count = 0
1598 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
1599 MOV INPUT_FLAG,NO_INPUT ;AN000; NO INPUT
1600 CALL PRINT_STDOUT ;AN000; Display message
1601
1602 POP AX ;AN000; GET IT BACK
1603; On return from prompt msg, AX contains Y or N response character
1604 MOV DL,AL ;AN000;
1605 MOV AH,65H ;AN000;
1606 MOV AL,023H ;AN000; Y/N check function
1607 INT 21H ;AN000; Issue Extended country to
1608 ; capitalize the Y/N response
1609 JC PPF_RETRY ;AN000; NOT Y OR N, ASK AGAIN
1610 CMP AX,1 ;AN000; look for Y
1611 JG PPF_RETRY ;AN000; NOT Y OR N, ASK AGAIN
1612
1613 CMP AX,0 ;AN000; look for N
1614 JE PPF_NO ;AN000;
1615PPF_YES:
1616 CLC ;AN000;CLEAR CARRY
1617 JMP SHORT PPF_EXIT
1618PPF_RETRY:
1619 JMP PPF_AGAIN ;AN000;ASK AGAIN
1620PPF_NO:
1621 STC ;AN000;set carry
1622PPF_EXIT:
1623 RET
1624PROMPT_PATH_FILE ENDP
1625;
1626
1627
1628
1629SET_MY_DTA PROC NEAR
1630;set DS:DX for find_first(next). If MY_FLAG is set to FINDFILE_FLAG then
1631;set it to the offset FILE_DTA, otherwise to BP.
1632;DS should be set to the area whre FILE_DTA, DTAS are.
1633 PUSH DX ;save current DX
1634 TEST MY_FLAG, FINDFILE_FLAG ;handling file?
1635; $IF NZ
1636 JZ $$IF78
1637 MOV DX, OFFSET FILE_DTA
1638; $ELSE
1639 JMP SHORT $$EN78
1640$$IF78:
1641 MOV DX, BP
1642; $ENDIF
1643$$EN78:
1644 MOV AH, Set_DTA
1645 INT 21H
1646 POP DX
1647 RET
1648SET_MY_DTA ENDP
1649;
1650
1651CHANGE_S_DIR PROC NEAR
1652;change source directory
1653;DS points to program data seg.
1654
1655 CMP S_DRV[2], 0 ;LAST_DIR_OUT have took '\' out?
1656; $IF E
1657 JNE $$IF81
1658 MOV S_DRV[2], '\' ;then restore '\' for root dir
1659 MOV S_DRV[3], 0
1660; $ENDIF
1661$$IF81:
1662
1663 TEST SYS_FLAG, ONE_DISK_COPY_FLAG ;one drive letter copy?
1664; $IF NZ,OR ;yes
1665 JNZ $$LL83
1666 TEST OPTION_FLAG, SLASH_M ;hard archive option? (should use full path
1667; $IF NZ ; since hard archieve operation will corrupt the current directory)
1668 JZ $$IF83
1669$$LL83:
1670 MOV DX, OFFSET S_DRV_PATH ;always use full path
1671; $ELSE
1672 JMP SHORT $$EN83
1673$$IF83:
1674 TEST MY_FLAG, VISIT_PARENT_FLAG ;now going toward the root?
1675; $IF NZ ;yes
1676 JZ $$IF85
1677 MOV DX, OFFSET S_PARENT ;just '..',0
1678; $ELSE
1679 JMP SHORT $$EN85
1680$$IF85:
1681 LEA DX, [BP].DTA_FILENAME ;use the subdir name just found
1682; $ENDIF
1683$$EN85:
1684; $ENDIF
1685$$EN83:
1686 MOV AH, Chdir ; = 3Bh
1687 INT 21H
1688; $IF C
1689 JNC $$IF89
1690 OR COPY_STATUS, CHDIR_ERROR_FLAG ;chdir error in source. critical
1691 CALL EXTENDED_ERROR_HANDLER
1692; $ENDIF
1693$$IF89:
1694
1695 RET
1696CHANGE_S_DIR ENDP
1697;
1698
1699CHANGE_T_DIR PROC NEAR
1700;change target dir according to t_drv_path.
1701;Since this routine is called by WRITE_FROM_BUFFER and DS now points
1702;to buffer area while ES points to the program data area, we set DS
1703;to data seg again here for the function call Chdir.
1704 PUSH DS ;save current buffer seg
1705 PUSH ES ;currentpy es is a data seg
1706 POP DS ;restore DS value as program data seg
1707
1708 CMP T_DRV[2], 0 ;LAST_DIR_OUT took '\' out?
1709; $IF E
1710 JNE $$IF91
1711 MOV T_DRV[2], '\' ;then put it back for root dir
1712 MOV T_DRV[3], 0
1713; $ENDIF
1714$$IF91:
1715
1716 MOV DX, OFFSET T_DRV_PATH
1717 MOV AH, CHDIR
1718 INT 21H
1719
1720 POP DS ;restore caller's DS value
1721 RET
1722CHANGE_T_DIR ENDP
1723;
1724
1725CMP_FILESIZE_TO_BUFFER_LEFT PROC NEAR
1726;Compare buffer_left (paragraph) with filesize (high_file_size, low_file_size.)
1727;if filesize is bigger than buffer_left, then set FILE_BIGGER_FLAG
1728;indicating filesize > buffer_left.
1729;
1730 PUSH DX
1731 PUSH AX
1732
1733 CMP OPEN_FILE_COUNT,NUL ;AN005;ARE THERE ANY OPEN FILES
1734; $IF Z ;AN005;NO, THEN GO AHEAD AND OPEN
1735 JNZ $$IF93
1736 CALL OPEN_A_FILE ;AN005;OPEN A FILE USING FILE_DTA
1737
1738; Get extended Attribute list size.
1739
1740 MOV BX,S_HANDLE ;AN005; BX = handle
1741 MOV AX, GET_ATTRIB ;AN005; extended attribute code 5702H
1742 MOV SI,ALL_ATTR ;AN005; SELECT ALL ATTRIBUTES SIZE
1743 XOR CX,CX ;AN005; JUST QUERY SIZE NEEDED
1744 MOV DI,NUL_LIST ;AN005; DI = LIST FOR NO DATA RETURNED
1745 INT 21H ;AN005; get extended attribute SIZE
1746 ADD CX,PARA_BOUND ;AN005; TO FIGURE THE NEXT PARAGRAPH
1747 MOV AX,CX ;AN005;
1748 MOV CL,PARAGRAPH ;AN005; GET PARAGRAPHS (DIV BY 16)
1749 SHR AX,CL ;AN005;
1750 MOV SIZ_OF_BUFF,AX ;AN005;SAVE BUFF SIZE FOR THE HEADER
1751 ADD AX,FIXD_HD_SIZ ;AN005;GET THE TOTAL HEADER SIZE
1752 MOV PARA_OF_HDR,AX ;AN005;SAVE FOR LATER
1753 SHL AX, CL ;AN005;CONVERT BACK TO TOTAL BYTES
1754 MOV BYTS_OF_HDR,AX ;AN005;SAVE FOR LATER
1755; $ENDIF ;AN005;
1756$$IF93:
1757
1758 AND FILE_FLAG, RESET_FILE_BIGGER
1759 MOV AX,PARA_OF_HDR ;AN005;GET THE HEADER SIZE (para.)
1760 CMP BUFFER_LEFT,AX ;AC005;buffer_left >= HEADER SIZE
1761; $IF AE
1762 JNAE $$IF95
1763 MOV AX, BUFFER_LEFT ;buffer_left in para
1764 SUB AX,PARA_OF_HDR ;AC005;consider header size in advance
1765 MOV CX, 16
1766 MUL CX ;* 16. result in DX;AX
1767 CMP HIGH_FILE_SIZE, DX
1768; $IF A ;if high_filesize > dx
1769 JNA $$IF96
1770 OR FILE_FLAG, FILE_BIGGER_FLAG
1771; $ELSE
1772 JMP SHORT $$EN96
1773$$IF96:
1774; $IF E
1775 JNE $$IF98
1776 CMP LOW_FILE_SIZE, AX
1777; $IF A
1778 JNA $$IF99
1779 OR FILE_FLAG, FILE_BIGGER_FLAG
1780; $ENDIF
1781$$IF99:
1782; $ENDIF
1783$$IF98:
1784; $ENDIF
1785$$EN96:
1786; $ELSE
1787 JMP SHORT $$EN95
1788$$IF95:
1789 OR FILE_FLAG, FILE_BIGGER_FLAG ;buffer_left < HEADER SIZE
1790; $ENDIF
1791$$EN95:
1792
1793 POP AX
1794 POP DX
1795 RET
1796CMP_FILESIZE_TO_BUFFER_LEFT ENDP
1797;
1798
1799SET_BUFFER_PTR PROC NEAR
1800;set BUFFER_PTR, BUFFER_LEFT, OLD_BUFFER_PTR in paragraph boundary
1801;to be used when reading a file into buffer.
1802;this routine uses current BUFFER_PTR to figure out the next BUFFER_PTR.
1803;So, at initialization time set BUFFER_PTR to CS, and set AX to the offset
1804;of INIT, then the resultant BUFFER_PTR indicates the BUFFER_BASE and
1805;OLD_BUFFER_PTR indicates CS.(This means if old_buffer_ptr = cs, then
1806;it is the start of buffer)
1807;To get the next BUFFER_PTR during multi-copy, just set the AX to the
1808;number of bytes read. This routine will add E.A.BUFFER SIZE + 3 para.
1809;for header size and will set the next BUFFER_PTR.
1810;input: AX - offset of buffer
1811; Top_of_memory in segment
1812; current BUFFER_PTR
1813; current OLD_BUFFER_PTR
1814; current BUFFER_LEFT
1815;output: BUFFER_PTR for next reading
1816; OLD_BUFFER_PTR
1817; BUFFER_LEFT (Top_of_memory - Buffer_Ptr. If it is 0, then indicates
1818; the BUFFER is FULL. In this case, the BUFFER_PTR is
1819; invalid, but OLD_BUFFER_PTR keep the former buffer_ptr
1820; value which says that it is the last header in the buffer)
1821;** Currently this program support maxium top of memory in seg 0FFFF - resident
1822; area. This routine will check the overflow case to gaurd the next buffer_ptr
1823; not to exceed FFFF.
1824
1825 PUSH CX
1826 MOV CX, BUFFER_PTR
1827 MOV OLD_BUFFER_PTR, CX ;set old_buffer_ptr
1828 MOV CL, 4
1829 SHR AX, CL ;get paragraphs
1830 INC AX ;get next paragraph
1831 ADD AX,PARA_OF_HDR ;AC005;consider header size
1832 ADD BUFFER_PTR, AX ;add this to the current buffer_ptr
1833
1834; $IF NC,AND ;not exceed 16 bit.
1835 JC $$IF105
1836 MOV AX, Top_of_memory
1837 SUB AX, BUFFER_PTR ;AX = Top_of_memory - Buffer_ptr
1838; $IF A ;if buffer_left > 0
1839 JNA $$IF105
1840 MOV BUFFER_LEFT, AX
1841; $ELSE
1842 JMP SHORT $$EN105
1843$$IF105:
1844 MOV BUFFER_LEFT, 0 ;indication of buffer full
1845; $ENDIF
1846$$EN105:
1847 POP CX
1848 RET
1849SET_BUFFER_PTR ENDP
1850;
1851
1852WRITE_FROM_BUFFER PROC NEAR
1853;Write from the first header starting at buffer_base until finishes
1854;the last header which, actually, happens to be the old_buffer_ptr
1855;at the time of the call. After the writing, reset the buffer_ptr
1856;to buffer_base again for the next read_into_buffer.
1857;If continue_info is 1 or 2 (Continue of small, bigfile) then after
1858;the creation of a target file, it will set the CREATED_FLAG.
1859;This flag will be reset when it found the continue_info to be 3
1860;(End of contine).
1861;For convenience of use of function call, ES will be used for
1862;the program data seg while DS will be used for the BUFFER seg.
1863;
1864 PUSH DS
1865 PUSH ES ;save ds, es
1866
1867 PUSH DS
1868 POP ES ;set ES to program data seg
1869
1870 OR ACTION_FLAG, READING_FLAG ;show reading message next time
1871; AND ES:MY_FLAG, RESET_IS_SOURCE ;now, deals with target
1872 ;set this for change_dir
1873 MOV AX, ES:BUFFER_BASE
1874 MOV DS, AX
1875 PUSH CS
1876 POP AX
1877 CMP ES:OLD_BUFFER_PTR, AX ;if old_buffer_ptr = CS then
1878 ;buffer is empty. Just exit
1879 JE WFB_EXIT_BRIDGE
1880WFB_CD:
1881 CALL CHANGE_T_DIR
1882 JC WFB_ERROR_BRIDGE ;error?
1883WFB_CHATT:
1884 CMP DS:ATTR_FOUND, Is_subdirectory ;a subdirectory? = 10H
1885 JNE WFB_FILE ;no. a file
1886WFB_CMP_DEPTH:
1887 MOV AH, ES:T_DEPTH ;yes. a subdir.
1888 CMP DS:DIR_DEPTH, AH ;DIR_DEPTH > T_DEPTH ?
1889 JBE WFB_DEC_DEPTH ;if not, go to parent node
1890 LEA DI, ES:T_DRV_PATH ;else goto child node
1891 LEA SI, DS:FILENAME_FOUND
1892 CMP ES:T_PATH, 0 ;root directory?
1893; $IF E
1894 JNE $$IF108
1895 MOV AL, 0FFh ;then don't need to put delim since it is already there
1896; $ELSE
1897 JMP SHORT $$EN108
1898$$IF108:
1899 MOV AL, Path_delim ;path_delim '\'
1900; $ENDIF
1901$$EN108:
1902 CALL CONCAT_ASCIIZ
1903 call concat_display_path ;modify the path for display
1904 INC ES:T_DEPTH
1905 CALL MAKE_DIR ;try to make a new sub directory
1906 JC WFB_EXIT_A_BRIDGE ;there exists a file with same name.
1907 MOV AX, DS ;current buffer seg = old_buffer_ptr?
1908 CMP ES:OLD_BUFFER_PTR, AX
1909 JNE WFB_NEXT ;not finished yet. jmp to next
1910 OR ES:MY_FLAG, MISSING_LINK_FLAG ;Finished. Missing link condition occurred regarding empty sub dir
1911 JMP WFB_EXIT_A ;check archieve options.
1912WFB_NEXT:
1913 MOV DS, DS:NEXT_PTR ;let's handles next header.
1914 JMP WFB_CD ;change directory first.
1915WFB_EXIT_BRIDGE: JMP WFB_EXIT
1916WFB_ERROR_BRIDGE: JMP WFB_ERROR
1917WFB_EXIT_A_BRIDGE: JMP WFB_EXIT_A
1918WFB_DEC_DEPTH:
1919 LEA DI, ES:T_DRV_PATH
1920 CALL RM_EMPTY_DIR ;check flags and remove empty dir
1921 CALL LAST_DIR_OUT ;take off the last dir from path
1922 call cut_display_path ;modify path for display purpose
1923 DEC ES:T_DEPTH ;and decrease depth
1924 JMP WFB_CD ;CHANGE DIR AND compare the depth again.
1925
1926WFB_FILE: ;Handling a file
1927 AND ES:MY_FLAG, RESET_MISSING_LINK ;if found a file, then current dir is not empty.
1928 TEST ES:FILE_FLAG, CREATED_FLAG ; A file handle is created ?
1929 JNZ WFB_WRITE ;yes, skip create again.
1930 CALL CREATE_A_FILE ;create a file in the cur dir
1931 JC WFB_ERROR ;file creation error?
1932WFB_WRITE:
1933 CALL WRITE_A_FILE
1934 JC WFB_EXIT_A ;target file has been already deleted.
1935 CMP DS:CONTINUE_INFO, 0
1936; $IF E,OR ;if continue_info = 0 or 3
1937 JE $$LL111
1938 CMP DS:CONTINUE_INFO, 3
1939; $IF E
1940 JNE $$IF111
1941$$LL111:
1942 MOV BX, ES:T_HANDLE
1943 CALL SET_FILE_DATE_TIME ;then set file's date, time
1944 PUSH DS ;AN005;SAVE THE BUFFER PTR
1945 PUSH ES ;AN005;WE NEED THE DATA PTR
1946 POP DS ;AN005;DS = THE DATA PTR
1947 CALL CLOSE_A_FILE ;and close the handle
1948 POP DS ;AN005;DS = THE BUFFER PTR AGAIN
1949 CALL RESTORE_FILENAME_FOUND ;if filename_found has been changed, restore it for reset_s_archieve.
1950 AND ES:FILE_FLAG, RESET_CREATED ;and reset created_flag
1951 CALL INC_FILE_COUNT ;increase file count
1952; $ENDIF
1953$$IF111:
1954 MOV AX, DS
1955 CMP ES:OLD_BUFFER_PTR, AX ;current header is the last one?
1956 JE WFB_EXIT_A ;then exit
1957 MOV DS, DS:NEXT_PTR ;else set ds to the next ptr
1958 JMP WFB_CHATT ;handle the next header
1959WFB_ERROR:
1960 jmp main_exit ;meaningful when MKDIR failed because
1961 ;of there already exist same named file,
1962 ;or disk_full case.
1963WFB_EXIT_A:
1964 test ES:option_flag, slash_m ;hard archieve ? - turn off source archieve bit.
1965 jz wfb_exit_B ;no, chk error flag and exit
1966 call reset_s_archieve ;reset source file(s) archieve bit using header info(s).
1967WFB_EXIT_B:
1968 test ES:copy_status, mkdir_error_flag ;mkdir error happened?
1969 JNZ WFB_ERROR ;yes, exit
1970 test ES:copy_status, disk_full_flag ;disk full happened?
1971 JNZ WFB_ERROR ;yes, exit
1972WFB_EXIT:
1973 MOV ES:OLD_BUFFER_PTR, CS ;set old_buffer_ptr to CS
1974 MOV AX, ES:BUFFER_BASE
1975 MOV ES:BUFFER_PTR, AX ;set buffer_ptr to base
1976 MOV AX, ES:MAX_BUFFER_SIZE
1977 MOV ES:BUFFER_LEFT, AX ;set buffer_left
1978 POP ES
1979 POP DS
1980 TEST SYS_FLAG, ONE_DISK_COPY_FLAG ;one drive letter copy?
1981; $IF NZ ;yes
1982 JZ $$IF113
1983 CALL CHANGE_S_DIR ;then change current dir to s dir
1984; $ENDIF
1985$$IF113:
1986 RET
1987WRITE_FROM_BUFFER ENDP
1988;
1989INC_FILE_COUNT PROC NEAR
1990;increase the file count by one.
1991;increase file_cnt_low, file_cnt_high.
1992;input: DS - buffer
1993; ES - data seg
1994 INC ES:FILE_CNT_LOW
1995 JNZ IFC_EXIT
1996 INC ES:FILE_CNT_HIGH ;if carry over, then inc file_cnt_high
1997IFC_EXIT:
1998 RET
1999INC_FILE_COUNT ENDP
2000;
2001RM_EMPTY_DIR PROC NEAR
2002;check the slash_E option, missing_link_flag. Remove the empty directory
2003;from the target disk.
2004;INPUT: DS - buffer
2005; ES - data seg
2006; DI - points to the current target drv, path
2007
2008 TEST ES:OPTION_FLAG, SLASH_E ;user want to copy empty subdir?
2009 JNZ RED_EXIT ;then exit
2010 TEST ES:MY_FLAG, MISSING_LINK_FLAG ;missing informations for not to copying empty dir
2011 ;at the tree travesal phase?
2012 JZ RED_EXIT ;no.
2013 CALL SWITCH_DS_ES ;ds - data, es - buffer
2014 MOV DX, OFFSET T_PARENT ;chdir to parent dir
2015 MOV AH, 3Bh ;Chdir
2016 INT 21h
2017 PUSH DI
2018 POP DX ;DS:DX points to drv, path
2019 MOV AH, 3Ah ;REMOVE SUBDIR
2020 INT 21h
2021 CALL SWITCH_DS_ES ;restore ds, es
2022RED_EXIT:
2023 RET
2024RM_EMPTY_DIR ENDP
2025;
2026RESTORE_FILENAME_FOUND PROC NEAR
2027;when the filename_found has been Revised according to the user's specified
2028;input parm, then restore the original source filename in filename_found.
2029;This will be used when reset_s_archieve routine reset the source file's
2030;archieve bit.
2031;input: DS - buffer
2032; ES - data seg
2033
2034 CMP ES:T_FILENAME, 0 ;if t_filename ot t_template is not blank,
2035; $IF NE,OR ;then filename_found has been Revised.
2036 JNE $$LL115
2037 CMP ES:T_TEMPLATE, 0
2038; $IF NE
2039 JE $$IF115
2040$$LL115:
2041 CALL SWITCH_DS_ES ;DS - data seg, ES - buffer
2042 MOV CX, 13
2043 LEA SI, DS:DISP_S_FILE ;we know filename_found has been save into DISP_S_FILE when create the file.
2044 LEA DI, ES:FILENAME_FOUND ;use this to restore source filename this time.
2045 REP MOVSB ;disp_s_file => filename_found
2046 CALL SWITCH_DS_ES ;restore ds, es
2047; $ENDIF
2048$$IF115:
2049 RET
2050RESTORE_FILENAME_FOUND ENDP
2051;
2052RESET_S_ARCHIEVE PROC NEAR
2053;INPUT: DS - buffer
2054; ES - data seg
2055
2056 TEST ES:COPY_STATUS, DISK_FULL_FLAG ;called when disk full?
2057 JZ RSA_START ;no, just goto start
2058 ;else disk_full.
2059 MOV AX, DS ;current DS when called
2060 CMP ES:BUFFER_BASE, AX ;current DS(BUFFER) is the first one?
2061 JE RSA_EXIT_BRIDGE ;yes, just exit
2062 MOV AX, DS:BEFORE_PTR ;set old_buffer_ptr to the header
2063 MOV ES:OLD_BUFFER_PTR, AX ;that is just before the troubled one.
2064RSA_START:
2065 MOV AX, ES:BUFFER_BASE
2066 MOV DS, AX ;set DS to buffer base again to start traveling
2067RSA_CD:
2068 CALL CHANGE_ARC_S_DIR ;change souce dir
2069RSA_CHATT:
2070 CMP DS:ATTR_FOUND, Is_subdirectory ; = 10h
2071 JNE RSA_FILE ;no a file
2072RSA_CMP_DEPTH:
2073 MOV AH, ES:S_ARC_DEPTH ;yes, a subdir
2074 CMP DS:DIR_DEPTH, AH ;dir_depth > s_arc_depth?
2075 JBE RSA_DEC_DEPTH ;if not, goto parent node
2076 LEA DI, ES:S_ARC_DRV_PATH
2077 LEA SI, DS:FILENAME_FOUND
2078 CMP ES:S_ARC_PATH, 0 ;root dir?
2079; $IF E
2080 JNE $$IF117
2081 MOV AL, 0FFh
2082; $ELSE
2083 JMP SHORT $$EN117
2084$$IF117:
2085 MOV AL, Path_delim ;path_delim '\'
2086; $ENDIF
2087$$EN117:
2088 CALL CONCAT_ASCIIZ
2089 INC ES:S_ARC_DEPTH
2090 MOV AX, DS
2091 CMP ES:OLD_BUFFER_PTR, AX
2092 JE RSA_EXIT_A ;finished. Set the source current dir and return to caller
2093 MOV DS, DS:NEXT_PTR ;else let's handles next header
2094 JMP RSA_CD ;chdir first.
2095RSA_EXIT_A:
2096 CALL CHANGE_ARC_S_DIR ;to restore the same current source dir
2097 ;as that of the READ_INTO_BUFFER proc.
2098RSA_EXIT_BRIDGE:JMP RSA_EXIT
2099RSA_DEC_DEPTH:
2100 LEA DI, ES:S_ARC_DRV_PATH
2101 CALL LAST_DIR_OUT
2102 DEC ES:S_ARC_DEPTH
2103 JMP RSA_CD
2104RSA_FILE:
2105 CMP DS:CONTINUE_INFO, 0
2106; $IF E,OR
2107 JE $$LL120
2108 CMP DS:CONTINUE_INFO, 3
2109; $IF E
2110 JNE $$IF120
2111$$LL120:
2112 CALL CHANGE_S_FILEMODE ;change source file mode
2113; $ENDIF
2114$$IF120:
2115 MOV AX, DS
2116 CMP ES:OLD_BUFFER_PTR, AX ;current header is the last one?
2117 JE RSA_EXIT
2118 MOV DS, DS:NEXT_PTR
2119 JMP RSA_CHATT
2120RSA_EXIT:
2121 OR ES:SYS_FLAG, DEFAULT_S_DIR_fLAG ;this is for restoring default source dir before exit to DOS.
2122 RET ;return to caller
2123RESET_S_ARCHIEVE ENDP
2124;
2125CHANGE_S_FILEMODE PROC NEAR
2126;input: DS - buffer
2127; ES - data seg
2128
2129 LEA DX, DS:FILENAME_FOUND
2130 MOV AH, 43h ;chmod
2131 MOV AL, 0 ;get attribute in CX
2132 INT 21h
2133 MOV AH, 43h
2134 MOV AL, 1
2135 AND CX, 0FFDFh ;turn off the archieve bit
2136 INT 21h
2137 RET
2138CHANGE_S_FILEMODE ENDP
2139;
2140CHANGE_ARC_S_DIR PROC NEAR
2141;change the source directory according to S_ARC_DRV_PATH
2142;INPUT: DS - buffer
2143; ES - data seg
2144 call switch_ds_es
2145 CMP S_ARC_DRV[2], 0
2146; $IF E
2147 JNE $$IF122
2148 MOV S_ARC_DRV[2], '\' ;LAST_DIR_OUT have took '\' out?
2149 MOV S_ARC_DRV[3],0 ;then restore it
2150; $ENDIF
2151$$IF122:
2152 MOV DX, OFFSET S_ARC_DRV_PATH ;use full drv, path
2153 MOV AH, CHDIR ; = 3Bh
2154 INT 21h
2155; $IF C
2156 JNC $$IF124
2157 OR COPY_STATUS, CHDIR_ERROR_FLAG
2158 CALL EXTENDED_ERROR_HANDLER
2159; $ENDIF
2160$$IF124:
2161 call switch_ds_es
2162 RET
2163CHANGE_ARC_S_DIR ENDP
2164
2165;
2166CONCAT_DISPLAY_PATH PROC NEAR
2167;concatenate subdirectory name found from the header to DISP_S_PATH which
2168;will be used for display copying file messages.
2169;if slash_p option has been set, then just return.
2170;DS: buffer header
2171;ES: data seg
2172;
2173 TEST ES:OPTION_FLAG, SLASH_P ;prompt option?
2174; $IF Z ;no
2175 JNZ $$IF126
2176 LEA DI, ES:DISP_S_PATH
2177 LEA SI, DS:FILENAME_FOUND
2178 CMP ES:T_DEPTH, 0 ;this will be the first child directory?
2179; $IF E ;yes
2180 JNE $$IF127
2181 MOV AL, 0FFh ;then do not put '\' between them
2182; $ELSE
2183 JMP SHORT $$EN127
2184$$IF127:
2185 MOV AL, Path_delim ;else put '\'
2186; $ENDIF
2187$$EN127:
2188 CALL CONCAT_ASCIIZ
2189; $ENDIF ;else just return
2190$$IF126:
2191 RET
2192CONCAT_DISPLAY_PATH ENDP
2193;
2194CUT_DISPLAY_PATH PROC NEAR
2195;take the last dir out from the DISP_S_PATH for display copy messages.
2196;if prompt option has been set, just return.
2197;INPUT: DS - buffer header
2198; ES - data seg
2199;
2200
2201 TEST ES:OPTION_FLAG, SLASH_P ;prompt?
2202; $IF Z ;no.
2203 JNZ $$IF131
2204 PUSH DS ;save DS
2205 PUSH ES
2206 POP DS ;ds = es = data seg
2207 MOV SI, OFFSET DISP_S_PATH ;for CHK_DRV_LETTER
2208 MOV DI, OFFSET DISP_S_PATH ;for LASR_DIR_OUT
2209
2210 CALL LAST_DIR_OUT
2211; $IF C ;failure? no '\' found
2212 JNC $$IF132
2213 CALL CHK_DRV_LETTER ;drive letter?
2214; $IF NC ;yes. "D:filename",0 case
2215 JC $$IF133
2216 MOV BYTE PTR DS:[SI], 0 ;make it "D:",0 since SI now points to the next chr
2217; $ELSE ;no. "filename",0 case
2218 JMP SHORT $$EN133
2219$$IF133:
2220 MOV BYTE PTR [DI], 0 ;set DISP_S_PATH to 0
2221; $ENDIF
2222$$EN133:
2223; $ELSE ;found '\' and last '\' became 0
2224 JMP SHORT $$EN132
2225$$IF132:
2226 CMP T_DEPTH, 1 ;now going to the starting path?
2227; $IF E ;yes. restore it for concat_display_path routine.
2228 JNE $$IF137
2229 MOV DI, AX ;we want to restore '\' and put 0 just after that.
2230 DEC DI ;for ex, "D:\DIR1"=>"D:"=>"D:\" -- original starting path
2231 MOV BYTE PTR [DI], '\' ; "D:dir1\dir2"=>"D:dir1"(starting path) => "D:dir1\"
2232 MOV BYTE PTR [DI+1], 0
2233; $ENDIF
2234$$IF137:
2235; $ENDIF
2236$$EN132:
2237 POP DS ;restore ds to buffer header
2238; $ENDIF
2239$$IF131:
2240 RET
2241CUT_DISPLAY_PATH ENDP
2242;
2243
2244
2245;***************************************************************************
2246CHK_DRV_LETTER PROC NEAR
2247; ** CHECK CURRENT CHR IS ALPHA CHR FOLLOWED BY COLON. *
2248; INPUT: DS:SI POINTS TO THE CURRENT CHR TO BE CHECKED. *
2249; OUTPUT: FOUND - SI POINTS TO THE NEXT CHR. *
2250; IF THIS HAD BEEN A LAST WORD, ZERO FLAG WILL BE SET. *
2251; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. *
2252;***************************************************************************
2253
2254 PUSH AX
2255 PUSH SI ;AN010;IN CASE DRIVE LETTER NOT FOUND
2256; $DO ;AN010;
2257$$DO141:
2258 CLC ;AN010;INITIALIZE TO NOT DBCS
2259 MOV AL,DS:BYTE PTR [SI] ;AN010;GET THE 1st CHAR TO TEST
2260 CALL CHK_DBCS ;AN010;SEE IF WE ARE IN DBCS
2261; $LEAVE NC ;AN010;THIS IS NOT DBCS
2262 JNC $$EN141
2263 INC SI ;AN010;GO TO THE NEXT CHAR TO CHECK
2264 INC SI ;AN010;DITO
2265; $ENDDO ;AN010;
2266 JMP SHORT $$DO141
2267$$EN141:
2268 CMP AL, 'A'
2269 JB CK_DR_1 ;LESS THAN 'A', THEN NOT FOUND.
2270 CMP AL, 'Z'
2271 JA CK_DR_1 ;ABOVE 'Z', THEN NOT FOUND.
2272 MOV AL, DS:BYTE PTR [SI+1] ;LOOK AHEAD THE FOLLOWING CHR.
2273 CMP AL, ':' ;SHOULD BE A COLON.
2274 JNZ CK_DR_1 ;NOT FOUND.
2275 POP AX ;AN010;THROW AWAY SAVED SI
2276 INC SI ;FOUND. SI TO THE NEXT CHR.
2277 INC SI
2278 JMP CK_DR_2
2279CK_DR_1:
2280 STC ;SET CARRY
2281 POP SI ;AN010;RESTORE SI TO ENTRY VALUE
2282CK_DR_2:
2283 POP AX
2284 RET
2285CHK_DRV_LETTER ENDP
2286;
2287
2288
2289CREATE_A_FILE PROC NEAR
2290;create a file in the header and return the file handle in T_HANDLE.
2291;Set CREATED_FLAG. This will be reset by WRITE_FROM_BUFFER when it
2292;close the handle.
2293;this routine will check the T_FILENAME and T_TEMPLATE if any target
2294;filename has been entered. If T_FILENAME is there, then DX will
2295;points to this (This is the case when the user has specified non_global
2296;chr filename and any source filename be changed to this name.)
2297;If T_TEMPLATE is present, then modify the filename found in the
2298;header part.
2299;Also, this routine show copy messages just before a file creation using
2300;FILENAME_FOUND.
2301;ES - data seg
2302;DS - buffer seg
2303
2304 PUSH DS
2305 PUSH ES
2306
2307 ;save the original filename from the header
2308 MOV CX, 13 ;max 13 chr
2309 LEA SI, DS:FILENAME_FOUND ;original source file name
2310 LEA DI, ES:DISP_S_FILE ;filename to be displayed
2311 REP MOVSB ;filename_found => disp_s_file
2312 test es:option_flag, slash_p
2313; $IF Z
2314 JNZ $$IF144
2315 CALL SHOW_COPY_MESSAGE ;show the source path, file
2316; $ENDIF
2317$$IF144:
2318
2319 CMP ES:T_FILENAME, 0
2320; $IF NE ;non_global target filename entered.
2321 JE $$IF146
2322 TEST ES:COPY_STATUS, MAYBE_ITSELF_FLAG
2323; $IF NZ
2324 JZ $$IF147
2325 LEA SI, DS:FILENAME_FOUND
2326 LEA DI, ES:T_FILENAME
2327 CALL COMP_FILENAME ;compare it. if same then show
2328 ;file cannot be copied onto itself and
2329 ;abort
2330; $ENDIF
2331$$IF147:
2332
2333 CALL SWITCH_DS_ES ;now ds - data, es - buffer
2334 MOV CX, 13
2335 LEA SI, DS:T_FILENAME
2336 LEA DI, ES:FILENAME_FOUND
2337 REP MOVSB ; t_filename => filename_found
2338 MOV AL, NUL ;AN014;DOS NEEDS A NUL TO TERM.
2339 MOV ES:TERMINATE_STRING,AL ;AN014;PUT IT IN THE HEADER
2340 CALL SWITCH_DS_ES ;now ds - buffer, es - data seg
2341
2342; $ELSE
2343 JMP SHORT $$EN146
2344$$IF146:
2345 CMP ES:T_TEMPLATE, 0 ;global chr target filename entered?
2346; $IF NE ;yes, entered. modify the filename found
2347 JE $$IF150
2348 CALL MODIFY_FILENAME
2349 TEST ES:COPY_STATUS, MAYBE_ITSELF_FLAG
2350; $IF NZ
2351 JZ $$IF151
2352 LEA SI, DS:FILENAME_FOUND ;compare the Revised filename
2353 LEA DI, ES:DISP_S_FILE ;with original name
2354 CALL COMP_FILENAME ;if same, then issue error message and exit
2355; $ENDIF
2356$$IF151:
2357; $ELSE
2358 JMP SHORT $$EN150
2359$$IF150:
2360 TEST ES:COPY_STATUS, MAYBE_ITSELF_FLAG ;*.* CASE
2361; $IF NZ
2362 JZ $$IF154
2363 PUSH ES
2364 POP DS ;ds - data seg
2365
2366 ; Set message parameters
2367 MOV AX,MSG_COPY_ITSELF ;AN000;
2368 MOV MSG_NUM,AX ;AN000; set message number
2369 MOV SUBST_COUNT,NO_SUBST ;AN000; no message subst.
2370 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
2371 MOV INPUT_FLAG,NO_INPUT ;AN000; no user input
2372 CALL PRINT_STDERR ;AN000; display error
2373 JMP MAIN_EXIT
2374; $ENDIF
2375$$IF154:
2376; $ENDIF
2377$$EN150:
2378; $ENDIF
2379$$EN146:
2380;-------------------------------------------------------------------------
2381; Use extended open DOS call to create the target file, use attribute list
2382; obtained from the previous Get Extended attribute DOS call
2383;-------------------------------------------------------------------------
2384 MOV AX, Ext_Open ;AN000; = 6Ch
2385 MOV BX,CREATE_MODE ;AN000;CREATE MODE = 0002H
2386 MOV CX,CREATE_ATTR ;AN000; attribute = 0
2387 MOV DX,CREATE_FLAG ;AN000; flag = 0112H
2388 MOV SI,OFFSET TARGET_DRV_LET ;AN005; DS:SI-->NAME TO CREATE
2389 MOV DI,NUL_LIST ;AN012; ES:DI = -1
2390 INT 21H ;AN000; create file
2391
2392 JC CAF_ERROR ;AN000;
2393 MOV ES:T_HANDLE, AX ;AN000;save handle
2394
2395 CALL CHK_T_RES_DEVICE ;check target handle is a reserved dev
2396
2397 MOV AX,SET_ATTRIB ;AN012;5704H
2398 CALL SWITCH_DS_ES ;AN013;now ds - data, es - buffer
2399 MOV BX,T_HANDLE ;AC013;THE FILE HANDLE
2400 LEA DI,ES:ATTRIB_LIST ;AN013;PARAMETER LIST (ES:DI)
2401 INT 21H ;AN012;SET EXTENDED ATTRIBUTES
2402 CALL SWITCH_DS_ES ;AN013;now es - data, ds - buffer
2403 JC CAF_ERROR ;AN012;
2404
2405 OR ES:FILE_FLAG, CREATED_FLAG ;set created_flag
2406 JMP CAF_EXIT
2407CAF_ERROR:
2408 PUSH DS
2409 PUSH ES
2410 POP DS
2411 OR COPY_STATUS, CREATE_ERROR_FLAG
2412 CALL EXTENDED_ERROR_HANDLER
2413 POP DS
2414CAF_EXIT:
2415 POP ES
2416 POP DS
2417 RET
2418CREATE_A_FILE ENDP
2419;
2420chk_t_res_device proc near
2421;check the target handle if it is for reserved device
2422;input: ES - data seg
2423; DS - buffer
2424; AX - filehandle created
2425
2426 cmp es:t_filename,0 ;if no user specified filename
2427 jne ctrd_ioctl ;then should not be a reserved device name
2428 cmp es:t_template,0
2429 je ctrd_exit
2430ctrd_ioctl:
2431 mov bx, ax ;file handle
2432 mov ax, 4400h ;IOCTL get device info.
2433 int 21h
2434 test dx, 80h ;is device? (not a block device?)
2435 jz ctrd_exit
2436 PUSH ES ;AN000;
2437 POP DS ;AN000;ds - data seg
2438
2439; Set message parameters
2440 MOV AX,MSG_RES_T_NAME ;AN000; message number
2441 MOV MSG_NUM,AX ;AN000; set message number
2442 MOV SUBST_COUNT,NO_SUBST ;AN000; no message substitution
2443 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
2444 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
2445 CALL PRINT_STDOUT ;AN000; display message
2446 jmp main_exit
2447ctrd_exit:
2448 ret
2449chk_t_res_device endp
2450;
2451MODIFY_FILENAME PROC NEAR
2452;modify the filename in the header using T_TEMPLATE.
2453;INPUT:
2454;DS: BUFFER
2455;ES: DATA SEG
2456
2457 PUSH DS ;save ds, es = data seg
2458 PUSH ES
2459
2460 PUSH DS
2461 PUSH ES
2462 MOV ES, ES:PSP_SEG ;ES points to PSP
2463 MOV DI, PSPFCB2_DRV ;DI points to FCB2, 6c
2464 MOV SI, OFFSET DS:TARGET_DRV_LET ;filename found, DS = buffer header
2465 MOV AH, 29H ;parse a filename
2466 MOV AL, 0 ;control bits
2467 INT 21h ;unfold the filename found into PSP FCB2 area
2468
2469 POP DS ;now DS=data seg, ES=PSP seg
2470 MOV SI, OFFSET T_TEMPLATE ;SI points to template
2471 MOV DI, PSPFCB2_DRV
2472 INC DI ;DI points to the formatted filename
2473 MOV CX, 11
2474 CLD
2475; $DO
2476$$DO158:
2477 CMP CX, 0 ;done?
2478; $LEAVE E ;yes. exit
2479 JE $$EN158
2480 LODSB ;[SI] => AL, SI = SI + 1
2481 CMP AL, '?' ;global chr?
2482; $IF E ;yes
2483 JNE $$IF160
2484 INC DI ;just skip the corresponding target chr
2485; $ELSE ;no
2486 JMP SHORT $$EN160
2487$$IF160:
2488 STOSB ;change the target chr to this. DI = DI + 1
2489; $ENDIF
2490$$EN160:
2491 DEC CX
2492; $ENDDO
2493 JMP SHORT $$DO158
2494$$EN158:
2495
2496 POP ES ;now ES = Buffer
2497 MOV DI, OFFSET ES:FILENAME_FOUND ; di points to filename in the header
2498 MOV DS, PSP_SEG ;DS = PSP seg
2499 MOV SI, PSPFCB2_DRV
2500 INC SI ;di points to Revised filename
2501 CALL COMPRESS_FILENAME ;fold it
2502
2503 POP ES
2504 POP DS
2505 RET
2506MODIFY_FILENAME ENDP
2507;
2508
2509COMP_FILENAME PROC NEAR
2510;this routine is called when MAYBE_COPY_ITSELF flag in on.
2511;SI, DI asciiz string will be compared and if they are identical
2512;the show "Cannot copy onto itself" msg and jmp to main_exit.
2513;INPUT: DS - buffer
2514; ES - data seg
2515
2516 CLD
2517 MOV AL, 0
2518 PUSH DI ;save DI
2519 CALL STRING_LENGTH ;CX get the length of string
2520 MOV BX, CX ;now, BX got the length of the target filename entered.
2521 PUSH BX ;save BX
2522 PUSH ES ;save ES
2523
2524 PUSH DS
2525 POP ES ;now ES set to DS
2526 PUSH SI
2527 POP DI ;now DI points to the source filename found.
2528
2529 MOV AL, 0
2530 CALL STRING_LENGTH ;CX got the length of the string
2531
2532 POP ES ;restore ES
2533 POP BX ;restore BX
2534 POP DI ;restore DI
2535
2536 CMP BX, CX ;COMPARE LENGTH
2537 JNE CF_EXIT ;IF THEY ARE DIFFERENT, EXIT
2538
2539 REPE CMPSB ;compare SI, DI until not equal,
2540 CMP CX, 0 ;finish at cx = 0?
2541 JE CF_SAME
2542 JMP SHORT CF_EXIT
2543CF_SAME:
2544 PUSH ES
2545 POP DS ;ds = data seg
2546
2547; Set message parameters
2548 MOV AX,MSG_COPY_ITSELF ;AN000; message number
2549 MOV MSG_NUM,AX ;AN000; set message number
2550 MOV SUBST_COUNT,NO_SUBST ;AN000; no message substitution
2551 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
2552 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
2553 CALL PRINT_STDERR ;AN000; display error message
2554 JMP MAIN_EXIT
2555CF_EXIT:
2556 RET
2557COMP_FILENAME ENDP
2558
2559;
2560SHOW_COPY_MESSAGE PROC NEAR
2561;show the source path, filename that is ready for creation in the target disk.
2562;INPUT: ES - data seg
2563; DS - buffer header seg
2564 PUSH DS ;save DS
2565
2566 PUSH ES
2567 POP DS ;DS = data seg
2568
2569 LEA SI,SUBLIST1 ;AN000; get addressability to list
2570 LEA DX,DISP_S_PATH ;AN000; offset to path name
2571 MOV [SI].DATA_OFF,DX ;AN000; save offset
2572 MOV [SI].DATA_SEG,DS ;AN000; save data segment
2573 MOV [SI].MSG_ID,1 ;AN000; message ID
2574 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
2575 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
2576 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
2577
2578 LEA SI,SUBLIST2 ;AN000; get addressability to list
2579 LEA DX,DISP_S_FILE ;AN000; offset to file name
2580 MOV [SI].DATA_OFF,DX ;AN000; save offset
2581 MOV [SI].DATA_SEG,DS ;AN000; save data segment
2582 MOV [SI].MSG_ID,2 ;AN000; message ID
2583 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
2584 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
2585 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
2586
2587 LEA SI,SUBLIST1 ;AN000;
2588 CMP ES:T_DEPTH, 0 ;starting directory?
2589; $IF E ;yes
2590 JNE $$IF164
2591 MOV AX,S_PATH_FILE0 ;AN000;NO BACK SLASH BETWEEN PATH,FNAME
2592
2593; $ELSE
2594 JMP SHORT $$EN164
2595$$IF164:
2596 MOV AX,S_PATH_FILE1 ;AN000;BACK SLASH IS BETWEEN PATH,FNAME
2597
2598; $ENDIF
2599$$EN164:
2600 MOV MSG_NUM,AX ;AN000; set message number
2601 MOV SUBST_COUNT,PARM_SUBST_TWO ;AN000; substitution count = 2
2602 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
2603 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
2604 CALL PRINT_STDOUT ;show message "Reading source
2605 POP DS ;restore DS
2606 RET
2607SHOW_COPY_MESSAGE ENDP
2608;
2609WRITE_A_FILE PROC NEAR
2610;write a file from the data area in the buffer.
2611;Remember the caller is WRITE_FROM_BUFFER which use ES for
2612;the program data area and DS for the header in the buffer.
2613
2614 MOV AH, Write ; = 40h
2615 MOV BX, ES:T_HANDLE ;handle saved in the program data area
2616 MOV DX, ES:BYTS_OF_HDR ;AC005;skip header
2617 MOV CX, DS:CX_BYTES ;get the # from the header
2618 INT 21h
2619 JC WAF_ERROR ;write error
2620 CMP AX, DS:CX_BYTES
2621 JNE WAF_DISKFULL
2622 JMP WAF_EXIT
2623WAF_ERROR:
2624 CALL CLOSE_DELETE_FILE ;close delete troubled file
2625 OR COPY_STATUS, WRITE_ERROR_FLAG
2626 CALL SWITCH_DS_ES ;AN000;DS = DATA SEG, ES = BUFFER
2627 CALL EXTENDED_ERROR_HANDLER
2628 CALL SWITCH_DS_ES ;AN000;ES = DATA SEG, DS = BUFFER
2629WAF_DISKFULL:
2630 MOV ERRORLEVEL, 4 ;set errorlevel
2631
2632; Set message parameters
2633; Target disk full, critical error
2634
2635 PUSH DS ;AN000;DS = BUFFER
2636 PUSH ES ;AN000;ES = DATA SEG
2637 POP DS ;AN000;ES => DS = DATA SEG
2638 MOV AX,MSG_DISK_FULL ;AN000; message number
2639 MOV MSG_NUM,AX ;AN000; set message number
2640 MOV SUBST_COUNT,NO_SUBST ;AN000; no message substitution
2641 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
2642 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
2643 CALL PRINT_STDERR ;AN000; display error message
2644 OR COPY_STATUS, DISK_FULL_FLAG ;set disk_full_flag
2645 POP DS ;AN000;RESTORE DS = BUFFER
2646 CALL CLOSE_DELETE_FILE
2647 STC ;set carry and return to caller
2648WAF_EXIT:
2649 RET
2650WRITE_A_FILE ENDP
2651;
2652SET_FILE_DATE_TIME PROC NEAR
2653;input: BX - target file handle
2654;
2655 MOV AH, File_date_time ; = 57h
2656 MOV AL, Set_file_time ; = 1
2657 MOV CX, DS:FILE_TIME_FOUND
2658 MOV DX, DS:FILE_DATE_FOUND
2659 INT 21h
2660 RET
2661SET_FILE_DATE_TIME ENDP
2662;
2663CLOSE_A_FILE PROC NEAR
2664;
2665;CLOSE A FILE AND UPDATE COUNT OF OPEN FILES
2666;
2667;INPUT: BX - file handle to be closed
2668;
2669 CMP OPEN_FILE_COUNT,NUL ;AN005;ARE THERE ANY OPEN FILES?
2670; $IF A ;AN005;
2671 JNA $$IF167
2672 DEC OPEN_FILE_COUNT ;AN005;IF SO, REDUCE THE COUNT BY 1.
2673; $ENDIF ;AN005;
2674$$IF167:
2675 MOV AH, Close ; = 3Eh
2676 INT 21H
2677 RET
2678CLOSE_A_FILE ENDP
2679;
2680DELETE_A_FILE PROC NEAR
2681;input: DS:DX - points to ASCIIZ string
2682
2683 MOV AH, 41h ; = 41h
2684 INT 21H
2685 RET
2686DELETE_A_FILE ENDP
2687;
2688MAKE_DIR PROC NEAR
2689;make a subdirectory in the current target directory.
2690;The directory name is in the header part Target_drv_Let
2691;with the drive letter.
2692;input:DS - buffer
2693; ES - data seg
2694
2695 MOV AH, Mkdir ; = 39h
2696 MOV DX, OFFSET DS:TARGET_DRV_LET ;target drv and filename
2697 INT 21h
2698 JC MD_ERROR
2699 JMP MD_EXIT
2700MD_ERROR:
2701;cannot distinguish between cases of: 1. already there exists a directory.
2702; 2. there has been a file exist with the same name in the target.
2703; 3. no disk space to make dir.
2704; Case 1, should ignore and just exit this routine
2705; Case 2, critical error.
2706; Case 3, critical error.
2707 call chk_disk_full ;check disk full condition first
2708 jc MD_EXIST ;AC026;yes, disk full, check if exist
2709 push es ;else check a file with the same name.
2710 push ds
2711 push dx
2712 mov ah, 2fH ;get current DTA addr in ES:BX
2713 int 21h
2714 mov ds, es:psp_seg
2715 mov dx, 80h
2716 mov ah, 1ah
2717 int 21h ;set dta to psp default dta area
2718 pop dx ;restore DX - target drv and filename
2719 pop ds ;restore DS - buffer
2720 mov cx, 6 ;HIDDEN + SYSTEM inclusive search
2721 mov ah, 4Eh ;FIND FIRST MATCHING FILE
2722 int 21h
2723 jc md_ok ;not found. There exists subdir. ignore
2724 stc ;else found a file with same name.
2725 jmp short MD_RESTORE
2726
2727MD_OK:
2728 clc ;else there exists dir., ignore error.
2729MD_RESTORE:
2730 pushf
2731 push ds ;save ds again - buffer
2732 push es ;es - save dta seg
2733 pop ds ;ds = saved DTA seg
2734 mov dx, bx ; saved DTA off
2735 mov ah, 1ah
2736 int 21h ;restore DTA
2737 pop ds ;restore ds
2738 popf
2739 pop es ;restore ES
2740 jnc md_exit ;if no error, then exit
2741 jmp md_err ;AN026;
2742
2743;else check a file with the same name.
2744
2745MD_EXIST:
2746 push es ;AN026;
2747 push ds ;AN026;
2748 push dx ;AN026;
2749 mov ah, 2fH ;AN026;get current DTA addr in ES:BX
2750 int 21h ;AN026;
2751 mov ds, es:psp_seg ;AN026;
2752 mov dx, 80h ;AN026;
2753 mov ah, 1ah ;AN026;
2754 int 21h ;AN026;set dta to psp default dta area
2755 pop dx ;AN026;restore DX - tar drv and filenm
2756 pop ds ;AN026;restore DS - buffer
2757 mov cx, 10h ;AN026;sub-directory search
2758 mov ah, 4Eh ;AN026;FIND FIRST MATCHING dir.
2759 int 21h ;AN026;
2760
2761 pushf ;AN026;save carry state
2762 push ds ;AN026;save ds again - buffer
2763 push es ;AN016;es - save dta seg
2764 pop ds ;AN026;ds = saved DTA seg
2765 mov dx, bx ;AN026; saved DTA off
2766 mov ah, 1ah ;AN026;
2767 int 21h ;AN026;restore DTA
2768 pop ds ;AN026;restore ds
2769 popf ;AN026;get carry state from find
2770 pop es ;AN026;restore ES
2771 jnc md_exit ;AN026;if no error, then dir. exits
2772
2773MD_ERR:
2774 call switch_ds_es ;switch ds, es
2775 mov errorlevel, 4 ;set the errorlevel to 4
2776 test copy_status, disk_full_flag ;disk full?
2777 jnz MD_FULL ;yes, full.
2778 mov ax,msg_unable_create ; else make dir fails because of
2779 ; the same file name
2780 or copy_status, mkdir_error_flag ;set make dir error flag
2781 jmp short MD_PRT
2782MD_FULL:
2783 mov ax,msg_disk_full
2784MD_PRT:
2785; Set message parameters
2786 PUSH ES ;AN017;ES = BUFFER
2787 PUSH DS ;AN017;DS = DATA SEG
2788 POP ES ;AN017;DS => ES = DATA SEG
2789 MOV MSG_NUM,AX ;AN000; set message number
2790 MOV SUBST_COUNT,NO_SUBST ;AN000; no message substitution
2791 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
2792 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
2793 CALL PRINT_STDERR ;AN000; display message
2794 POP ES ;AN017;RESTORE ES = BUFFER
2795
2796 call switch_ds_es ;restore ds, es
2797 stc ;error - set carry
2798MD_EXIT:
2799 RET
2800MAKE_DIR ENDP
2801;
2802CHK_DISK_FULL PROC NEAR
2803;check target disk space, and if no more clusters then set carry, disk_full_flag.
2804;this routine is called by MAKE_DIR routine.
2805;INPUT: DS - buffer
2806; ES - data seg
2807 PUSH AX
2808 PUSH BX
2809 PUSH CX
2810 PUSH DX
2811 MOV AH, 36h ;GET DISK FREE SPACE
2812 MOV DL, ES:T_DRV_NUMBER ;OF TARGET
2813 INT 21h
2814 CMP BX, 0 ;NO MORE CLUSTER?
2815 JE CDF_FULL
2816 CLC
2817 JMP SHORT CDF_EXIT
2818CDF_FULL:
2819 OR ES:COPY_STATUS, DISK_FULL_FLAG ;SET DISK FULL FLAG
2820 STC ;SET CARRY
2821CDF_EXIT:
2822 POP DX
2823 POP CX
2824 POP BX
2825 POP AX
2826 RET
2827
2828CHK_DISK_FULL ENDP
2829;
2830
2831CHK_FILE_NOT_FOUND PROC NEAR
2832;if FILE_CNT_LOW=FILE_CNT_HIGH=FOUND_FILE_FLAG=0 AND NO INIT ERROR,
2833; then show "File not found" msg
2834;INPUT: ES, DS = data seg
2835
2836 TEST PARM_FLAG, INIT_ERROR_FLAG
2837; $IF Z,AND ;no init error
2838 JNZ $$IF169
2839 CMP FILE_CNT_LOW, 0
2840; $IF E,AND
2841 JNE $$IF169
2842 CMP FILE_CNT_HIGH, 0
2843; $IF E,AND
2844 JNE $$IF169
2845 CMP FOUND_FILE_FLAG, 0
2846; $IF E
2847 JNE $$IF169
2848 MOV ES, PSP_SEG ;use PSP area for parsing
2849 MOV DI, PSPFCB1_DRV
2850 MOV SI, OFFSET S_FILE
2851 MOV AH, 29h
2852 MOV AL, 0 ;control byte
2853 INT 21h
2854 CALL SWITCH_DS_ES ;now, ds - psp seg, es - data seg
2855 MOV DI,OFFSET DISP_S_FILE
2856 MOV SI,PSPFCB1_DRV
2857 INC SI ;now SI points to the formatted filename area
2858 CALL COMPRESS_FILENAME ;[pspfcb1_drv+1] => disp_s_file
2859 PUSH ES
2860 POP DS ;now DS=ES=data seg
2861 LEA SI,SUBLIST1 ;AN000;
2862 MOV DI,OFFSET DISP_S_FILE ;AN000;
2863 MOV [SI].DATA_OFF,DI ;AN000; SI-->File name
2864 MOV [SI].DATA_SEG,DS ;AN000; DS-->Segment
2865 MOV [SI].MSG_ID,0 ;AN018; message ID
2866 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
2867 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
2868 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
2869 MOV AX,MSG_FILE_NOT_ERR ;AN018;
2870 MOV MSG_NUM,AX ;AN000; set message number
2871 MOV SUBST_COUNT,PARM_SUBST_ONE ;AN000; substitution count
2872 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
2873 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
2874 CALL PRINT_STDOUT ;AN000; display message
2875; $ENDIF
2876$$IF169:
2877
2878 RET
2879
2880CHK_FILE_NOT_FOUND ENDP
2881
2882;
2883subttl string_length
2884page
2885;******************************************************************************
2886;PURPOSE: Get the length of a string pointed by ES:DI until it encounters
2887; the same character given by the user in AL.
2888; The length will be an output in CX. The number includes the
2889; charater found.
2890; For example, if you want to determine the length of an ASCIIZ string,
2891; set ES:DI to that string and set AL to 0. The output CX is the
2892; total length of the ASCIIZ string including 0.
2893; So, if the first character pointed by DI is the same as that of AL,
2894; then the length will be 1.
2895; !!! It is the user's responsibility to make it sure that the string
2896; contains the character given in AL. If not, unpredictable
2897; results will occur.!!!
2898;
2899; DATA INPUT
2900; REGISTERS: AL - ASCII CHARACTER
2901; ES:DI - POINTER TO THE STRING.
2902; DATA OUTPUT
2903; REGISTERS: AX,DX,SI etc - PRESERVED.
2904; BX - DISTROYED
2905; CX - STRING LENGTH UNTIL FOUND THE GIVEN CHARACTER.
2906; DI - POINTS TO THE NEXT CHARACTER AFTER THE STRING.
2907; DIRECTION FLAG - CLEARED
2908; ZERO FLAG - RESET
2909;******************************************************************************
2910;
2911STRING_LENGTH PROC NEAR
2912PUBLIC STRING_LENGTH
2913 CLD ;CLEAR DIRECTION
2914 MOV BX,DI ;SAVE ORIGINAL DI VALUE
2915 MOV CX,80H ;TRY MAX 128 BYTES
2916 REPNE SCASB ;SCAN THE STRING UNTIL FOUND
2917 PUSH DI ;SAVE CURRENT DI VALUE WHICH POINTS TO NEXT CHR AFTER STRING
2918 SUB DI,BX ;GET THE LENGTH
2919 MOV CX,DI ;MOV THE LENGTH TO CX
2920 POP DI
2921 RET
2922STRING_LENGTH ENDP
2923;
2924subttl concat_asciiz
2925page
2926;******************************************************************************
2927;PURPOSE: Concatenate two ASCIIZ string into one ASCIIZ string.
2928; The ASCIIZ string pointed by DS:SI will be concatenated to
2929; the one pointed by ES:DI. The result string will be pointed by
2930; ES:DI.
2931; AL is used to put the delimeter character in between the strings.
2932; If you *DON'T* like to put the delimeter ***make AL to 0FFh***.
2933; For example, assume sting1 "ABCDE",0 pointed by DI and string2
2934; "FGHI",0 pointed by SI.
2935; If you want a delimeter "\" between two string, set AL to "\"
2936; before calling. The result will "ABCDE\FGHI",0 pointed by DI.
2937; If you set AL to "0FFh", then it becomes "ABCDEFGHI",0.
2938; This feature is useful for handling PATH if you set AL to "\"
2939; and, for any general string processes if you set AL to "0FFh".
2940; This routine will call subroutine STRING_LENGTH.
2941;DATA INPUT
2942; REGISTERS: AL - DELIMETER OR 0FFh
2943; ES:DI - POINTER TO THE DESTINATION STRING.
2944; DS:SI - POINTER TO THE SOURCE TO BE CONCATENATED.
2945;DATA OUTPUT
2946; REGISTERS: AL, DX - preserved
2947; DI - preserved. POINTER TO THE RESULT STRING
2948; SI - DISTROYED
2949; CX - RESULT ASCIIZ STRING LENGTH INCLUDE 0
2950; DIRECTION FLAG - CLEARED
2951;******************************************************************************
2952CONCAT_ASCIIZ PROC NEAR
2953
2954PUBLIC CONCAT_ASCIIZ
2955 PUSH DI ;SAVE POINTER VALUE WHICH WILL BE RETRUNED TO CALLER.
2956 PUSH AX ;SAVE VALUE IN AL.
2957 MOV AL, 0 ;DEALING WITH ASCIIZ STRING
2958 CALL STRING_LENGTH ;LET DI POINTS TO THE NEXT CHR AFTER THIS STRING
2959 ;DIRECTION WILL BE CLEARED.
2960 DEC DI ;MAKE DI POINT TO THE LAST CHARACTER 0
2961 POP AX ;RESTORE AL.
2962 CMP AL, 0FFh
2963; $IF NE ;IF THE USER WANTS TO PUT DIMIMETER,
2964 JE $$IF171
2965 STOSB ; REPLACE 0 WITH IT.
2966; $ELSE
2967 JMP SHORT $$EN171
2968$$IF171:
2969 DEC CX ;ELSE DECREASE LENGTH BY 1
2970; $ENDIF
2971$$EN171:
2972; $DO
2973$$DO174:
2974 LODSB ;MOV [SI] TO AL
2975 STOSB ;STORE AL TO [DI]
2976 INC CX ;INCREASE LENGTH
2977 CMP AL, 0 ;WAS IT A LAST CHARACTER?
2978; $ENDDO E ;THEN EXIT THIS LOOP
2979 JNE $$DO174
2980 POP DI
2981 RET
2982CONCAT_ASCIIZ ENDP
2983;
2984
2985subttl last_dir_out
2986page
2987;******************************************************************************
2988;PURPOSE: Take off the last directory name from the path pointed by DI.
2989; This routine assumes the pattern of a path to be an ASCIIZ string
2990; in the form of "[d:][\]dir1\dir2". Notice that this path does not
2991; have entailing "\". This routine will simply travel the string
2992; until it found last "\" which will, then, be replaced with 0.
2993; If no "\" found, then carry will be set.
2994; *** This should be not be used for the path in the form of
2995; *** "d:\", 0 for the root directory, since in this case the returned
2996; *** string will be "d:",0 and AX value returned be meaningless (Just
2997; *** points to 0.)
2998;DATA INPUT
2999; REGISTERS: DI - points to an ASCIIZ path string.
3000; ES - assumed default segment for DI
3001;DATA OUTPUT
3002; REGISTERS: DI - points to the resultant path string.
3003; AX - offset value of the last subdirectory name taken out, in case
3004; of the user's need.
3005; Other register will be unchanged.
3006; CARRY FLAG WILL SET IF NOT FOUND.
3007;******************************************************************************
3008
3009LAST_DIR_OUT PROC NEAR
3010PUBLIC LAST_DIR_OUT
3011
3012 PUSH DI
3013 PUSH SI ;save current DI, SI
3014 CLD ;clear direction
3015 MOV SI, 0FFFFh ;used as a not_found flag if unchanged.
3016; $DO
3017$$DO176:
3018; $DO ;AN010;
3019$$DO177:
3020 CLC ;AN010;INITIALIZE TO NOT DBCS
3021 MOV AL,BYTE PTR [DI] ;AN010;GET THE 1st CHAR TO TEST
3022 CALL CHK_DBCS ;AN010;SEE IF WE ARE IN DBCS
3023; $LEAVE NC ;AN010;THIS IS NOT DBCS
3024 JNC $$EN177
3025 INC DI ;AN010;GO TO THE NEXT CHAR TO CHECK
3026 INC DI ;AN010;DITO
3027; $ENDDO ;AN010;
3028 JMP SHORT $$DO177
3029$$EN177:
3030 MOV AL, 0
3031 SCASB
3032; $LEAVE Z ;if [DI] = 0, then end of string. Ends this loop.
3033 JZ $$EN176
3034 DEC DI ;if [DI] <> 0, then go back and scan char again
3035 MOV AL, "\" ;to see it was a back slash.
3036 SCASB
3037; $IF Z ;if it was, then save the addr to SI.
3038 JNZ $$IF181
3039 PUSH DI
3040 POP SI
3041
3042 DEC SI
3043; $ENDIF ;else do loop again.
3044$$IF181:
3045; $ENDDO
3046 JMP SHORT $$DO176
3047$$EN176:
3048 CLC ;clear carry flag.
3049 CMP SI, 0FFFFh ;Had SI been changed?
3050; $IF E
3051 JNE $$IF184
3052 STC ;No, set the carry. Not found.
3053; $ELSE
3054 JMP SHORT $$EN184
3055$$IF184:
3056 MOV BYTE PTR ES:[SI], 0 ;Yes, replace "\" with 0. Seg override to get default DI seg.
3057 MOV AX, SI
3058 INC AX ;let AX have the last dir offset value.
3059 CLC ;clear carry
3060; $ENDIF
3061$$EN184:
3062 POP SI ;restore original value
3063 POP DI ;original string offset
3064 RET
3065LAST_DIR_OUT ENDP
3066;
3067; HEADER <CHK_DBCS -SEE IF SPECIFIED BYTE IS A DBCS LEAD BYTE>
3068;*****************************************************************************
3069; Check DBCS environment
3070;*****************************************************************************
3071
3072; Function: Check if a specified byte is in ranges of the DBCS lead bytes
3073; Input: AL = Code to be examined
3074; Output: If CF is on then a lead byte of DBCS
3075; Register: FL is used for the output, others are unchanged.
3076
3077 PUBLIC CHK_DBCS
3078Chk_DBCS PROC ;AN010;
3079 PUSH DS ;AN010; save these regs, about to be clobbered
3080 PUSH SI ;AN010;
3081 CMP DBCSEV_SEG,0 ;AN010; ALREADY SET ?
3082; $IF E ;AN010; if the vector not yet found
3083 JNE $$IF187
3084 PUSH AX ;AN010;
3085 MOV AX,6300H ;AN010; GET DBCS EV CALL
3086 INT 21H ;AN010; ds:si points to the dbcs vector
3087
3088 ASSUME DS:NOTHING ;AN010; that function clobbered old DS
3089
3090 MOV DBCSEV_OFF,SI ;AN010; remember where the dbcs vector is
3091 MOV DBCSEV_SEG,DS ;AN010; so next time I don't have to look for it
3092 POP AX ;AN010;
3093; $ENDIF ;AN010;
3094$$IF187:
3095 LDS SI,DWORD PTR DBCSEV_OFF ;AN010;SET DS:SI TO POINT TO THE DBCS VECTOR
3096; $SEARCH ;AN010;
3097$$DO189:
3098 CMP WORD PTR [SI],0 ;AN010; vector ends with a nul terminator entry
3099; $LEAVE E ;AN010; if that was the terminator entry, quit
3100 JE $$EN189
3101 CMP AL,[SI] ;AN010; look at LOW value of vector
3102; $EXITIF NB,AND ;AN010; if this byte is in range with respect to LOW
3103 JB $$IF189
3104 CMP AL,[SI+1] ;AN010; look at HIGH value of vector
3105; $EXITIF NA ;AN010; if this byte is still in range
3106 JA $$IF189
3107 STC ;AN010; set flag to say, found a DBCS char.
3108; $ORELSE ;AN010; since char not in this vector
3109 JMP SHORT $$SR189
3110$$IF189:
3111 ADD SI,2 ;AN010; go look at next vector in dbcs table
3112; $ENDLOOP ;AN010; go back and check out new vector entry
3113 JMP SHORT $$DO189
3114$$EN189:
3115 CLC ;AN010; set flag to say, this is not a DBCS character
3116; $ENDSRCH ;AN010;
3117$$SR189:
3118 POP SI ;AN010; restore the regs
3119 POP DS ;AN010;
3120
3121; ASSUME DS:DSEG ;AN010; tell masm, DS back to normal
3122
3123 RET ;AN010;
3124chk_DBCS ENDP ;AN010;
3125;
3126;
3127
3128subttl Compress_Filename
3129page
3130
3131;
3132;******************************************************************************
3133;
3134; PURPOSE:
3135; --------
3136; Compress the FCB style filename into an ASCIIZ packed name.
3137; For example, 'ABC?????EXE' = > 'ABC?????.EXE',0
3138; or 'ABC EXE' = > 'ABC.EXE',0
3139; Note that the length of the source is *** 11 *** byte long.
3140; The max length of result is *** 13 *** bytes long.
3141; In the usual practice, the source filename with extention can be obtained
3142; by using function call 29h (Parse a Filename). So this routine is
3143; an inverse function of fun. 29h except DI should be the *** starting point
3144; of destination string *** instead of that of an unopened FCB (When you use
3145; fun 29h together with this routine, keep this thing in mind. Also if ES, DS
3146; values are different in your program, be careful to use them correctly.)
3147;------------------------------------------------------------------------------
3148; REGISTERS INPUT
3149; ----------------
3150; AX:
3151; BX:
3152; CX:
3153; DX:
3154; SI: offset of source unpacked filename with extention
3155; DI: offset where the resultant asciiz filename(.ext) will be placed.
3156; SP:
3157; BP:
3158; DS: source seg
3159; ES: result seg
3160; SS:
3161;
3162; DATA INPUT
3163; -----------
3164; Memory_Label -
3165;
3166;-----------------------------------------------------------------------------
3167; REGISTERS OUTPUT
3168; ----------------
3169; AX:
3170; BX:
3171; CX:
3172; DX:
3173; SI:
3174; DI:
3175; SP:
3176; BP:
3177; DS:
3178; ES:
3179; SS:
3180;
3181; DATA OUTPUT
3182; -----------
3183;
3184; FLAG OUTPUT
3185; -----------
3186;******************************************************************************
3187
3188COMPRESS_FILENAME PROC NEAR
3189PUBLIC COMPRESS_FILENAME
3190 PUSH DI
3191 XOR CX, CX ;CX = 0
3192; $DO
3193$$DO195:
3194 LODSB ;[SI] => AL, SI = SI + 1
3195 CMP CX, 10 ;CX > 10 then exit
3196; $LEAVE A
3197 JA $$EN195
3198 CMP CX, 8 ;filename extention position
3199; $IF B ;CX < 8. handling filename
3200 JNB $$IF197
3201 CMP AL, ' ' ;AL = blank ?
3202; $IF E
3203 JNE $$IF198
3204 MOV AX, 7
3205 SUB AX, CX
3206 ADD SI, AX ;SI = SI + (7 - CX)
3207 MOV CX, 8 ;then skip to handles extention
3208; $ELSE
3209 JMP SHORT $$EN198
3210$$IF198:
3211 STOSB ;AL => [DI], DI = DI + 1
3212 INC CX ;CX = CX + 1
3213; $ENDIF
3214$$EN198:
3215; $ELSE ;extention part
3216 JMP SHORT $$EN197
3217$$IF197:
3218 CMP AL, ' '
3219; $IF E
3220 JNE $$IF202
3221 MOV CX, 11 ;exit this loop
3222; $ELSE
3223 JMP SHORT $$EN202
3224$$IF202:
3225 CMP CX, 8 ;the first chr of extention?
3226; $IF E ;yes
3227 JNE $$IF204
3228 PUSH AX ;save cur chr
3229 MOV AL, '.' ;and put a dot
3230 STOSB ; . => [DI], DI = DI + 1
3231 POP AX ;restore AX
3232; $ENDIF
3233$$IF204:
3234 STOSB ;AL => [DI], DI = DI + 1
3235 INC CX ;CX = CX + 1
3236; $ENDIF
3237$$EN202:
3238; $ENDIF
3239$$EN197:
3240; $ENDDO
3241 JMP SHORT $$DO195
3242$$EN195:
3243 MOV AL, 0
3244 STOSB ;put 0 at the current [DI]
3245
3246 POP DI ;restore DI
3247 RET
3248COMPRESS_FILENAME ENDP
3249;
3250
3251
3252SET_DEFAULT_DRV PROC NEAR
3253;change source drv as a default drv for conveniece of find, read operation
3254;of source. (handling target should be more specific as for as drive letter
3255;goes.)
3256;input: DL - drive # (0 = A, 1 = B ...)
3257
3258 MOV AH, Select_Disk ; = 0Eh
3259 INT 21H
3260 OR SYS_FLAG, DEFAULT_DRV_SET_FLAG ;indicates default drv has been changed
3261 ;Used for exit the program to restore default drv
3262 RET
3263SET_DEFAULT_DRV ENDP
3264;
3265
3266
3267ORG_S_DEF PROC NEAR
3268;restore the original source directory.
3269 PUSH ES
3270 PUSH DS
3271
3272 PUSH DS
3273 POP ES ;DS=ES=data seg
3274
3275 TEST SYS_FLAG, DEFAULT_S_DIR_FLAG ;source default direcotry saved?
3276; $IF NZ
3277 JZ $$IF209
3278 MOV DX, OFFSET SAV_S_DRV ;saved source drive letter & directory
3279 MOV AH, 3Bh
3280 INT 21h ;restore source
3281 AND SYS_FLAG, RESET_DEFAULT_S_DIR ;reset the flag
3282; $ENDIF
3283$$IF209:
3284
3285 POP DS
3286 POP ES
3287
3288 RET
3289ORG_S_DEF ENDP
3290;
3291ORG_S_T_DEF PROC NEAR
3292;retore original target, source and default drv and directory
3293;check default_s(t)_dir_flag, default_drv_set_flag to restore source,
3294;or target directory and default drive.
3295
3296 TEST SYS_FLAG, TURN_VERIFY_OFF_FLAG ;turn off verify?
3297; $IF NZ ;yes
3298 JZ $$IF211
3299 MOV AX, 2E00h ;turn it off
3300 INT 21H
3301; $ENDIF
3302$$IF211:
3303 TEST SYS_FLAG, DEFAULT_DRV_SET_FLAG ;default drive has been changed?
3304; $IF NZ ;yes
3305 JZ $$IF213
3306 MOV DL, SAV_DEFAULT_DRV
3307 DEC DL
3308 CALL SET_DEFAULT_DRV ;restore default drv.
3309
3310; Following is a fix for PTR 0000012 . The fix is to skip changing default
3311; drive directory if source drive is not the default drive.
3312
3313 MOV AL, S_DRV_NUMBER ;AN002; get source drive number
3314 CMP AL, SAV_DEFAULT_DRV ;AN002; src drive is the default drv ?
3315; $IF NE ;AC022;NO, SO SEE IF DEF. DRV. IS CHGD.
3316 JE $$IF214
3317 TEST SYS_FLAG, DEFAULT_DRV_SET_FLAG ;AN022;DEF DRV CHGD?
3318; $IF NZ ;AN022;YES, RESET IT
3319 JZ $$IF215
3320 MOV DX, OFFSET SAV_DEF_DIR_ROOT ;AN022;GET THE SETTING
3321 MOV AH, Chdir ;AN022;MAKE THE CALL
3322 INT 21H ;AN022;
3323; $ENDIF ;AN022;
3324$$IF215:
3325; $ELSE ;AN022;SRC IS DEF DRIVE!
3326 JMP SHORT $$EN214
3327$$IF214:
3328 MOV DX, OFFSET SAV_DEF_DIR_ROOT
3329 MOV AH, Chdir
3330 INT 21H ;restore current dir of default dir
3331; $ENDIF ;AN022;
3332$$EN214:
3333; $ENDIF
3334$$IF213:
3335
3336
3337 TEST SYS_FLAG, DEFAULT_S_DIR_FLAG ;source default direcotry saved?
3338; $IF NZ
3339 JZ $$IF220
3340 MOV DX, OFFSET SAV_S_DRV ;saved source drive letter & directory
3341 MOV AH, 3Bh
3342 INT 21h ;restore source. This is for the case of ERROR exit.
3343; $ENDIF
3344$$IF220:
3345
3346 TEST SYS_FLAG, DEFAULT_T_DIR_FLAG ;target default directory saved?
3347; $IF NZ ;then assume both source, target default saved
3348 JZ $$IF222
3349 MOV DX, OFFSET SAV_T_DRV ;saved target drive letter & directory
3350 MOV AH, 3Bh
3351 INT 21h ;restore target
3352; $ENDIF
3353$$IF222:
3354
3355 RET
3356ORG_S_T_DEF ENDP
3357;
3358
3359CHK_MKDIR_LVL PROC NEAR
3360;if starting target directories has been created, and no files has been found to copy,
3361;and /E option is not specified, then remove the directories created.
3362;
3363 CMP T_MKDIR_LVL, 0 ;target starting directory created?
3364; $IF A,AND ;yes.
3365 JNA $$IF224
3366 TEST OPTION_FLAG, SLASH_E ;/E option taken?
3367; $IF Z,AND ;no.
3368 JNZ $$IF224
3369 CMP FOUND_FILE_FLAG, 0 ;found any file?
3370; $IF E
3371 JNE $$IF224
3372 CALL T_RM_STARTING_DIR ;then, remove created directories.
3373; $ENDIF
3374$$IF224:
3375 RET
3376CHK_MKDIR_LVL ENDP
3377;
3378
3379T_RM_STARTING_DIR PROC NEAR
3380;based on the current target directory, remove directories T_MKDIR_LVL times
3381;INPUT: T_MKDIR_LVL
3382; T_DRV_NUMBER
3383; T_DRV_PATH
3384; T_PATH
3385
3386
3387 MOV DL, T_DRV_NUMBER
3388 LEA SI, T_PATH
3389 MOV AH, Get_Current_Directory
3390 INT 21h
3391
3392TRSD_AGAIN:
3393 MOV DX, OFFSET T_PARENT ;chdir to the parent directory
3394 MOV AH, 3Bh ;Chdir
3395 INT 21h
3396 MOV DX, OFFSET T_DRV_PATH
3397 MOV AH, 3Ah ;Rmdir
3398 INT 21h
3399 MOV DI, OFFSET T_DRV_PATH
3400 CALL LAST_DIR_OUT ;take out the last removed dir name
3401 DEC T_MKDIR_LVL ;decrease the number
3402 CMP T_MKDIR_LVL, 0 ;no more?
3403 JA TRSD_AGAIN
3404
3405 RET
3406T_RM_STARTING_DIR ENDP
3407;
3408
3409
3410;************************************************************
3411;*
3412;* SUBROUTINE NAME: PRINT_STDOUT
3413;*
3414;* SUBROUTINE FUNCTION:
3415;* Display the requested message to the specified handle
3416;*
3417;* INPUT:
3418;* Paramters in parater storage area
3419;* DS:SI-->Substitution List
3420;* ES:DI-->PTR to input buffer if buffered keyboard
3421;* input is specified (DL = 0A)
3422;* OUTPUT:
3423;* AX = Single character entered if DL=01
3424;* OR
3425;* ES:DI-->input buffer where string is returned if DL=0A
3426;*
3427;* The message corresponding to the requested msg number will
3428;* be written to Standard Out. Message substitution will
3429;* be performed if specified
3430;*
3431;* NORMAL EXIT:
3432;* Message will be successfully written to requested handle.
3433;*
3434;* ERROR EXIT:
3435;* None. Note that theoretically an error can be returned from
3436;* SYSDISPMSG, but there is nothing that the application can do.
3437;*
3438;* INTERNAL REFERENCES: SysDispMsg
3439;*
3440;* EXTERNAL REFERENCES:
3441;* None
3442;*
3443;************************************************************
3444PRINT_STDOUT PROC NEAR ;AN000:
3445
3446 PUSH BX ;AN000;
3447 PUSH CX ;AN000;
3448 PUSH DX
3449
3450 MOV AX,MSG_NUM ;AN000; Message ID
3451 MOV BX,STDOUT ;AN000; standard input message handle
3452 MOV CX,SUBST_COUNT ;AN000; message substitution count
3453 MOV DH,MSG_CLASS ;AN000; message class
3454 MOV DL,INPUT_FLAG ;AN000; Type of INT 10 for KBD input
3455
3456 CALL SYSDISPMSG ;AN000: AX=Extended key value if wait
3457 ;for key
3458 JNC DISP_DONE ;AN000: If CARRY SET then registers
3459 ;will contain extended error info
3460 ; AX - Extended error Number
3461 ; BH - Error Class
3462 ; BL - Suggested action
3463DISP_DONE: ;AN000: CH - Locus
3464 POP DX
3465 POP CX ;AN000;
3466 POP BX ;AN000;
3467
3468 RET ;AN000:
3469PRINT_STDOUT ENDP ;AN000:
3470
3471
3472
3473
3474;************************************************************
3475;*
3476;* SUBROUTINE NAME: PRINT_STDERR
3477;*
3478;* FUNCTION: Display the requested message to Standard Out
3479;*
3480;* INPUT:
3481;* Parameters in parameter storage area
3482;* DS:SI-->Substitution List
3483;* ES:DI-->PTR to input buffer if buffered keyboard
3484;* input is specified (DL = 0A)
3485;*
3486;* OUTPUT:
3487;* AX = Single character entered if DL=01
3488;* OR
3489;* ES:DI-->input buffer where string is returned if DL=0A
3490;* The message corresponding to the requested msg number will
3491;* be written to the Standard Error. Message substitution will
3492;* be performed if specified
3493;*
3494;* NORMAL EXIT:
3495;* Message will be successfully written to requested handle.
3496;*
3497;* ERROR EXIT:
3498;* None. Note that theoretically an error can be returned from
3499;* SYSDISPMSG, but there is nothing that the application can do.
3500;*
3501;* INTERNAL REFERENCES: SysDispMsg
3502;*
3503;* EXTERNAL REFERENCES: None
3504;*
3505;************************************************************
3506PRINT_STDERR PROC NEAR ;AN000:
3507
3508 PUSH AX ;AN000;
3509 PUSH BX ;AN000;
3510 PUSH CX ;AN000;
3511 PUSH DX
3512
3513 MOV AX,MSG_NUM ;AN000; Message ID
3514 MOV BX,STDERR ;AN000; Handle
3515 MOV CX,SUBST_COUNT ;AN000; message substitution count
3516 MOV DH,MSG_CLASS ;AN000; message class
3517 MOV DL,INPUT_FLAG ;AN000; INT 10 KBD input type
3518
3519 CALL SYSDISPMSG ;AN000: AX=Extended key value if wait
3520 ;for key
3521 JNC DISP_EXIT ;AN000: If CARRY SET then registers
3522 ;will contain extended error info
3523 ; AX - Extended error Number
3524 ; BH - Error Class
3525 ; BL - Suggested action
3526DISP_EXIT: ;AN000: CH - Locus
3527 POP DX
3528 POP CX ;AN000;
3529 POP BX ;AN000;
3530 POP AX ;AN000;
3531 RET ;AN000:
3532
3533PRINT_STDERR ENDP ;AN000:
3534
3535
3536
3537
3538
3539;
3540EXTENDED_ERROR_HANDLER PROC NEAR
3541;This routine calls fun 59(Get extended error) and
3542;check the actions returned. If it is Immediate exit, then jmp to JUST_EXIT
3543;If it is abort, then jmp to MAIN_EXIT.
3544;Or else, it check the COPY_STATUS flag. If is not open, read, create or
3545;write, then it is considered as a critical error and jmp to MAIN_EXIT.
3546;If access denied
3547; too many open files
3548; sharing violation
3549; lock violation
3550; general failure
3551;then show the message and jmp to the MAIN_EXIT.
3552; *** Currently, this routine directly jump to the main_exit instead of
3553; *** returing to the caller. The reason is we regard the above error conditions
3554; *** as being not suitable to continue copying and, hence, to simplify
3555; *** the error process.
3556;INPUT:
3557; DS - DATA SEG
3558;OUTPUT:
3559; ALL THE REG PRESERVED
3560
3561 PUSH ES ;save ES
3562 PUSH AX
3563 PUSH BX
3564 PUSH CX
3565 PUSH DS ;AN000;
3566 POP ES ;AN000;DS = ES = DATA SEG
3567 PUSHF ;save flags
3568
3569 PUSH ES
3570 MOV AH, 59h ;get extended error
3571 MOV BX, 0 ;version 3.0
3572 INT 21h
3573 POP ES
3574
3575 MOV ERRORLEVEL, 4 ;error in operation
3576 TEST COPY_STATUS, OPEN_ERROR_FLAG ;open error?
3577 JNZ OPEN_ERROR_RTN ;yes
3578 TEST COPY_STATUS, READ_ERROR_FLAG ;read error?
3579 JNZ READ_ERROR_RTN
3580 TEST COPY_STATUS, CREATE_ERROR_FLAG ;create error?
3581 JNZ CREATE_ERROR_RTN
3582 TEST COPY_STATUS, WRITE_ERROR_FLAG ;write error?
3583 JNZ WRITE_ERROR_RTN
3584 TEST COPY_STATUS, CHDIR_ERROR_FLAG ;chdir error?
3585 JNZ CHDIR_ERROR_RTN
3586 JMP SHORT GOTO_MAIN_EXIT
3587
3588OPEN_ERROR_RTN: ;open error. show error message and exit
3589 CALL SHOW_S_PATH_FILE_ERR ;show the troubled path filename
3590 CALL SHOW_ERROR_MESSAGE
3591 JMP SHORT GOTO_MAIN_EXIT ;abort
3592
3593READ_ERROR_RTN:
3594 CALL SHOW_S_PATH_FILE_ERR
3595 CALL SHOW_ERROR_MESSAGE ;show message and abort
3596 JMP SHORT GOTO_MAIN_EXIT
3597
3598CREATE_ERROR_RTN:
3599 CMP AX, 2 ;"file not found" to create?
3600 JNE CER_1
3601; Set message parameters
3602 MOV AX,MSG_FILE_CREATE_ERR ;AN000; message number
3603 MOV MSG_NUM,AX ;AN000; set message number
3604 MOV SUBST_COUNT,NO_SUBST ;AN000; no message substitution
3605 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
3606 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
3607 CALL PRINT_STDERR ;show "File creation error" message
3608 ;instead of "File not found"
3609 JMP SHORT GOTO_MAIN_EXIT
3610CER_1:
3611 CALL SHOW_ERROR_MESSAGE ;show error_message
3612 JMP SHORT GOTO_MAIN_EXIT
3613WRITE_ERROR_RTN:
3614 CALL SHOW_ERROR_MESSAGE ;show message
3615 JMP SHORT GOTO_MAIN_EXIT
3616CHDIR_ERROR_RTN:
3617
3618 PUSH AX ;AN000;
3619; Set substitution list
3620 LEA SI,SUBLIST1 ;AN000; get addressability to sublist
3621 LEA DX,S_DRV_PATH ;AN000; offset to PATH NAME
3622 MOV [SI].DATA_OFF,DX ;AN000; save offset
3623 MOV [SI].DATA_SEG,DS ;AN000; save data segment
3624 MOV [SI].MSG_ID,1 ;AN000; message ID
3625 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
3626 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
3627 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
3628
3629; Set message parameters
3630 MOV AX,DISPLAY_S_PATH ;AN000; message number
3631 MOV MSG_NUM,AX ;AN000; set message number
3632 MOV SUBST_COUNT,PARM_SUBST_ONE ;AN000; one message substitution
3633 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
3634 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
3635 CALL PRINT_STDERR ;show source drv,path
3636 POP AX ;AN000;
3637 CALL SHOW_ERROR_MESSAGE ;display error message
3638
3639GOTO_MAIN_EXIT:
3640 JMP MAIN_EXIT ;restore conditions
3641 ;and exit
3642QUICK_EXIT:
3643 JMP JUST_EXIT ;immediate exit
3644
3645EEH_EXIT:
3646 MOV ERRORLEVEL, 0 ;reset errorlevel
3647 POPF
3648 POP CX
3649 POP BX
3650 POP AX
3651 POP ES
3652 RET
3653
3654EXTENDED_ERROR_HANDLER ENDP
3655;
3656
3657
3658SHOW_ERROR_MESSAGE PROC NEAR
3659;called immediately after Get_extended error
3660;This will show simple error message according to error_code in AX
3661;If the message is not what it wanted, just exit without message- Set carry.
3662;input: DS - data seg
3663;output: Carry flag is distroyed.
3664
3665 clc ;clear carry
3666 CMP AX, 5 ;access denied?
3667 JE ACCESS_DENIED_MESSAGE
3668 CMP AX, 4 ;too many open files?
3669 JE TOO_MANY_OPEN_MESSAGE
3670 CMP AX, 31 ;general failure?
3671 JE GENERAL_FAIL_MESSAGE
3672 CMP AX, 32 ;sharing violation?
3673 JE SHARING_VIOL_MESSAGE
3674 CMP AX, 33 ;lock violation?
3675 JE LOCK_VIOL_MESSAGE
3676 CMP AX, 3 ;path not found?
3677 JE PATH_NOT_MESSAGE
3678 CMP AX, 2 ;file not found error?
3679 JE FILE_NOT_ERR_MESSAGE
3680 CMP AX, 65 ;access denied on the network?
3681 JE ACCESS_DENIED_MESSAGE
3682 CMP AX, 82 ;no more directory entry to create a file?
3683 JE FILE_CREATE_ERR_MESSAGE
3684
3685 STC ;else set carry
3686
3687
3688 JMP GOTO_MAIN_EXIT ;and exit
3689
3690ACCESS_DENIED_MESSAGE:
3691 MOV AX, MSG_ACCESS_DENIED ;AN000;
3692 JMP SHORT SHOW_MESSAGE
3693TOO_MANY_OPEN_MESSAGE:
3694 MOV AX, MSG_TOO_MANY_OPEN ;AN000;
3695 JMP SHORT SHOW_MESSAGE
3696GENERAL_FAIL_MESSAGE:
3697 MOV AX, MSG_GENERAL_FAIL ;AN000;
3698 JMP SHORT SHOW_MESSAGE
3699SHARING_VIOL_MESSAGE:
3700 MOV AX, MSG_SHARING_VIOL ;AN000;
3701 JMP SHORT SHOW_MESSAGE
3702LOCK_VIOL_MESSAGE:
3703 MOV AX, MSG_LOCK_VIOL ;AN000;
3704 JMP SHORT SHOW_MESSAGE
3705PATH_NOT_MESSAGE:
3706 MOV AX, MSG_PATH_NOT ;AN000;
3707
3708 JMP SHORT SHOW_MESSAGE
3709FILE_NOT_ERR_MESSAGE:
3710 MOV AX, MSG_FILE_NOT_ERR ;AN000;
3711 JMP SHORT SHOW_MESSAGE
3712FILE_CREATE_ERR_MESSAGE:
3713 MOV AX, MSG_FILE_CREATE_ERR ;AN000;
3714
3715
3716SHOW_MESSAGE: ; Display error message
3717; Set message parameters
3718 MOV MSG_NUM,AX ;AN000; set message number
3719 MOV SUBST_COUNT,NO_SUBST ;AN000; NO message substitution
3720 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
3721 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
3722 CALL PRINT_STDERR ;AN000; print it
3723 RET
3724
3725SHOW_ERROR_MESSAGE ENDP
3726;
3727
3728
3729SHOW_S_PATH_FILE_ERR PROC NEAR
3730;show current source path(drv, full path), and filename to the
3731;standard error display device.
3732;input: ds: data seg
3733 PUSH ES ;save ES
3734 PUSH AX ;save ERROR_CODE
3735 push ds
3736 pop es ;es = ds
3737 MOV DI,OFFSET S_DRV_PATH
3738 CALL STRING_LENGTH ;cx got the length
3739 MOV SI,OFFSET S_DRV_PATH ;full path of source
3740 MOV DI,OFFSET DISP_S_PATH
3741 REP MOVSB ;S_DRV_PATH => DISP_S_PATH
3742 MOV CX, 13 ;max 13 chr
3743 MOV SI,OFFSET FILE_DTA.DTA_FILENAME
3744 MOV DI,OFFSET DISP_S_FILE
3745 REP MOVSB ;dta_filename => disp_s_file
3746
3747 LEA SI,SUBLIST1 ;AN000; get addressability to list
3748 LEA DX,DISP_S_PATH ;AN000; offset to path name
3749 MOV [SI].DATA_OFF,DX ;AN000; save offset
3750 MOV [SI].DATA_SEG,DS ;AN000; save data segment
3751 MOV [SI].MSG_ID,1 ;AN000; message ID
3752 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
3753 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
3754 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
3755
3756 LEA SI,SUBLIST2 ;AN000; get addressability to list
3757 LEA DX,DISP_S_FILE ;AN000; offset to file name
3758 MOV [SI].DATA_OFF,DX ;AN000; save offset
3759 MOV [SI].DATA_SEG,DS ;AN000; save data segment
3760 MOV [SI].MSG_ID,2 ;AN000; message ID
3761 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
3762 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
3763 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
3764
3765
3766 CMP S_DEPTH,0 ;AN000;it happened, when dealing with the starting dir?
3767; $IF E
3768 JNE $$IF226
3769 LEA SI,SUBLIST2 ;AN007;PIONT TO THE FIRST LIST
3770 MOV [SI].MSG_ID,1 ;AN007; message ID
3771 MOV AX,DISPLAY_S_PATH ;AC007;ITS ONLY A FILE NAME
3772 MOV SUBST_COUNT,PARM_SUBST_ONE ;AN007; ONE message sub
3773; $ELSE
3774 JMP SHORT $$EN226
3775$$IF226:
3776 LEA SI,SUBLIST1 ;AN007;PIONT TO THE FIRST LIST
3777 MOV AX,S_PATH_FILE1 ;AN000;put '\'
3778 MOV SUBST_COUNT,PARM_SUBST_TWO ;AN007;TWO message subs
3779; $ENDIF
3780$$EN226:
3781
3782; Set message parameters
3783
3784 MOV MSG_NUM,AX ;AN000; set message number
3785 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000; message class
3786 MOV INPUT_FLAG,NO_INPUT ;AN000; no input
3787 CALL PRINT_STDERR ;display error message
3788
3789 POP AX ;restore ERROR_CODE
3790 POP ES
3791 RET
3792
3793SHOW_S_PATH_FILE_ERR ENDP
3794;
3795
3796
3797CLOSE_DELETE_FILE PROC NEAR
3798;when writing error occurs, then this routine is called to
3799;clean up the troubled target file.
3800;INPUT: DS - buffer seg
3801; ES - data seg
3802
3803 MOV BX, ES:T_HANDLE ;close target file
3804 PUSH DS ;AN005;SAVE THE BUFFER PTR
3805 PUSH ES ;AN005;WE NEED THE DATA PTR
3806 POP DS ;AN005;DS = THE DATA PTR
3807 CALL CLOSE_A_FILE ;and close the handle
3808 POP DS ;AN005;DS = THE BUFFER PTR AGAIN
3809 LEA DX, DS:target_drv_let ;target drv, filename
3810 CALL DELETE_A_FILE ;delete it
3811 RET
3812CLOSE_DELETE_FILE ENDP
3813;
3814;
3815
3816SWITCH_DS_ES PROC NEAR
3817; switch DS, ES
3818 PUSH DS
3819 PUSH ES
3820 POP DS
3821 POP ES
3822 RET
3823SWITCH_DS_ES ENDP
3824
3825
3826
3827MY_INT24:
3828 CMP CS:INT24_ABORT_CNT, 0 ;if aborted more than once, then just exit.
3829 JNE MI_JUST_EXIT
3830 PUSHF ;we are calling interrupt handler
3831 CALL DWORD PTR CS:SAV_INT24 ;call original int 24 handler
3832 CMP AL, 1 ;retry?
3833 JE MI_RETRY
3834 CMP AL, 0 ;ignore? Cannot ignore. Try again
3835 JE MI_RETRY
3836 POP CX ;remove IP, CS, FLAGS
3837 POP CX ;since we are not going back
3838 POP CX ;to the place int 24 was called.
3839 CMP AL, 2 ;abort?
3840 JE MI_ABORT
3841 CMP AL, 3 ;AN000;fail?
3842 JE MI_ABORT
3843 JMP MAIN_EXIT ;show files copied message
3844 ;restore default value and exit
3845MI_ABORT:
3846 INC CS:INT24_ABORT_CNT ;increase the count of int24_abort
3847 JMP MAIN_EXIT_A ;restore default value and exit
3848MI_JUST_EXIT:
3849 POP CX
3850 POP CX
3851 POP CX
3852 JMP JUST_EXIT
3853MI_RETRY:
3854 IRET ;return where it happened
3855 ;and retry that operation.
3856;
3857INT24_ABORT_CNT DB 0
3858;
3859include msgdcl.inc
3860
3861CSEG ENDS
3862DSEG_INIT SEGMENT PARA PUBLIC ;AN000;
3863DSEG_INIT ENDS ;AN000;
3864 END MAIN
3865
3866 \ No newline at end of file
diff --git a/v4.0/src/CMD/XCOPY/XCOPY.EQU b/v4.0/src/CMD/XCOPY/XCOPY.EQU
new file mode 100644
index 0000000..cb2f02d
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/XCOPY.EQU
@@ -0,0 +1,144 @@
1;XCOPY EQUATES
2;*****************************************************************************
3; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
4; Remove the BELL char.,turn off APPEND during TREE
5; search,Extended Attribute processing, Uppercasing
6; and "Out Of Space" during write to standard out.
7; A004 PTM0700 9/02/87 Avoid duplicate switches and
8; display parm in error.
9; A005 DCR0201 9/11/87 Incorperate new format for EXTENDED
10; ATTRIBUTES.
11;*****************************************************************************
12;Equates used for flags
13;*** MY_FLAG ****
14 find_first_flag equ 01h ;set MY_FLAG by "OR"
15 findfile_flag equ 02h
16 no_more_file equ 04h
17 single_copy_flag equ 08h ;single copy instead of multi copy
18 visit_parent_flag equ 10h ;visit parent node
19 found_flag equ 20h ;found flag - for find subdir
20 missing_link_flag equ 40h
21 is_source_flag equ 80h ;if set, dealing with source
22 reset_find_first equ 0FEh ;reset by AND
23 reset_findfile equ 0FDh
24 reset_no_more equ 0FBh
25 reset_visit_parent equ 0EFh
26 reset_found equ 0DFh
27 reset_missing_link equ 0BFh
28 reset_is_source equ 07Fh
29
30;*** FILE_FLAG ***
31 cont_flag equ 01h
32 eof_flag equ 02h
33 big_file_flag equ 04h
34 file_bigger_flag equ 08h
35 created_flag equ 10h
36 reset_cont equ 0FEh
37 reset_eof equ 0FDh
38 reset_big_file equ 0FBh
39 reset_file_bigger equ 0F7h
40 reset_created equ 0EFh
41 reset_readfile equ 0F0h ;reset FILE_FLAG for read a file
42
43;*** COPY_STATUS ***
44 open_error_flag equ 01h
45 read_error_flag equ 02h
46 create_error_flag equ 04h
47 write_error_flag equ 08h
48 mkdir_error_flag equ 10h
49 chdir_error_flag equ 20h
50 maybe_itself_flag equ 40h ;source, target starting drv, directory is same.
51 disk_full_flag equ 80h
52 reset_open_error equ 0FEh
53 reset_read_error equ 0FDh
54 reset_create_error equ 0FBh
55 reset_write_error equ 0F7h
56 reset_close_error equ 0EFh
57 reset_chdir_error equ 0DFh
58
59
60;*** ACTION_FLAG ***
61
62 reading_flag equ 01h ;display "Reading source files..."
63 reset_reading equ 0FEh ;do not display.
64
65;*** SYS_FLAG ***
66
67 one_disk_copy_flag equ 01h
68 default_drv_set_flag equ 02h ;default drive has been changed by this program
69 default_s_dir_flag equ 04h ;source current directory saved.
70 default_t_dir_flag equ 08h ;target current directory saved.
71 removalble_drv_flag equ 10h
72 sharing_source_flag equ 20h ;source shared
73 sharing_target_flag equ 40h
74 turn_verify_off_flag equ 80h ;turn the verify off when exit to dos.
75 reset_default_s_dir equ 0FBh ;reset default_s_dir_flag
76
77;*** OPTION_FLAG ***
78
79 slash_a equ 01h ;soft archieve ?
80 slash_d equ 02h ;date?
81 slash_e equ 04h ;create empty dir?
82 slash_m equ 08h ;hard archieve ? (turn off source archieve bit)
83 slash_p equ 10h ;prompt?
84 slash_s equ 20h ;walk the tree?
85 slash_v equ 40h ;verify on?
86 slash_w equ 80h ;show "Press any key to begin copying" msg)
87 reset_slash_a equ 0FEh ;turn off soft archieve
88 reset_slash_m equ 0F7h ;turn off hard archieve
89
90;*** PARM_FLAG ***
91
92 first_parm_flag equ 01h ;first parm entered in input parm
93 second_parm_flag equ 02h ;second parm entered.
94 end_of_parm_flag equ 04h ;end of parm reached
95 copy_onto_itself_flag equ 08h ;copy onto itself flag
96 cyclic_flag equ 10h ;cyclic copy flag
97 inv_time_flag equ 20h ;invalid time
98 inv_date_flag equ 40h ;invalid date
99 init_error_flag equ 80h ;critical initialization error. Should abort.
100
101;*** PARM1_FLAG ***
102
103 inv_s_path_flag equ 01h ;invalid source path (path not found)
104 inv_t_path_flag equ 02h ;invalid target path
105 s_file_flag equ 04h ;source filename entered
106 t_file_flag equ 08h ;target filename entered
107 INV_SW_flag equ 10h ;AN004;DUPLICATE OR INVALID SW ENTERED
108
109;general equates
110
111COLON EQU ":" ;AN000;FOLLOWS DRV LTR IN FULL FILESPEC
112NUL EQU 0 ;AN000;DELIMITER FOR ASCIIZ STRINGS
113SPACE EQU " " ;AN000;TEST FOR DBCS IN 'F D ' MESSAGE
114PARAGRAPH EQU 4 ;AN005;TO CONVERT TO/FROM BYTES/PARA.
115PARA_BOUND EQU 15 ;AN005;BYTES TO ADD FOR PARA. CALCULAT
116FIXD_HD_SIZ EQU 3 ;AC015;PARA COUNT MINIMUM FOR FILE HDR
117SYSPRM_EX_MANY EQU 1 ;AN000;TOO MANY OPERANDS ERR FROM PARSE
118SYSPRM_MISSING_OP EQU 2 ;AN000;MISSING OPERANDS ERR FROM PARSE
119SYSPRM_DUP_SW EQU 3 ;AN004;INVALID SWITCH R-CODE FROM PARSE
120F_APPEND EQU 8000H ;AN000; /X status bit in Append
121D_V_APPEND EQU -1 ;AN019;DOS VERSION OF APPEND
122PSPFCB1_DRV EQU 5Ch
123PSPFCB2_DRV EQU 6Ch
124PSPDTA_PARMLEN EQU 80h
125PSPDTA_PARRSTR EQU 81h
126BASE_OF_ALPHA_DRV EQU 64 ;1 => A, 2 => B for drive letter
127BASE_UPPER_CASE EQU 11011111B ;"AND"ed will make it to upper case chr
128ALPHA_A EQU 'A'
129;ALPHA_D EQU 'D' ;moved to XCPYINT.MSG file for translation.
130ALPHA_E EQU 'E'
131;ALPHA_F EQU 'F' ;moved to XCPYINT.MSG file for translation.
132ALPHA_M EQU 'M'
133ALPHA_S EQU 'S'
134ALPHA_P EQU 'P'
135ALPHA_T EQU 'T'
136ALPHA_V EQU 'V'
137ALPHA_W EQU 'W'
138ALPHA_Z EQU 'Z'
139A_dot EQU '.'
140path_delim equ '\'
141drv_delim equ ':'
142;**********************************************************************
143;DOS_LEVEL EQU 0314h ;VERSION 3.20
144;*************************END OF XCOPY.EQU ****************************
diff --git a/v4.0/src/CMD/XCOPY/XCOPY.LNK b/v4.0/src/CMD/XCOPY/XCOPY.LNK
new file mode 100644
index 0000000..ff48255
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/XCOPY.LNK
@@ -0,0 +1,4 @@
1XCOPY+
2XCPYINIT+
3XCOPYPAR ;
4 \ No newline at end of file
diff --git a/v4.0/src/CMD/XCOPY/XCOPY.SKL b/v4.0/src/CMD/XCOPY/XCOPY.SKL
new file mode 100644
index 0000000..43a1fde
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/XCOPY.SKL
@@ -0,0 +1,83 @@
1;==========================================================
2; XCOPY MESSAGE SKELETON FILE
3;==========================================================
4
5:util XCOPY ;AN000;
6
7
8:class A ;AN000;System message class
9
10:use 1 COMMON1 ;AN000;MSG 1 is always "Incorrect DOS Version"
11
12:use 2 EXTEND8 ;AN000;MSG 2 is always "Insufficient Memory"
13
14:use 3 PARSE10 ;AN000;PARSER MSG 10 "Invalid parameter"
15
16:def 4 "Does %1 specify a file name",CR,LF ;AN000;
17 "or directory name on the target",CR,LF
18 "(F = file, D = directory)?"
19
20:def 5 "Press any key to begin copying file(s)" ;AN000;
21
22:def 6 "Path too long",CR,LF ;AN000;
23
24:use 7 COMMON25 ;AN000;"Invalid path"
25
26:def 8 "Cannot perform a cyclic copy",CR,LF ;AN000;
27
28:use 9 COMMON23 ;AN000;"Invalid date"
29
30:use 10 COMMON32 ;AN000;"Unable to create directory"
31
32:use 11 EXTEND15 ;AN000;"Invalid drive specification"
33
34:def 12 "Cannot XCOPY from a reserved device",CR,LF ;AN000;
35
36:use 13 EXTEND5 ;AN000;"Access denied"
37
38:use 14 EXTEND4 ;AN000;"Too many open files"
39
40:use 15 EXTEND31 ;AN000;"General failure"
41
42:use 16 EXTEND32 ;AN000;"Sharing Violation"
43
44:use 17 EXTEND33 ;AN000;"Lock Violation"
45
46:use 18 EXTEND3 ;AN000;"Path not found"
47
48:use 19 COMMON20 ;AN000;"Insufficient disk space"
49
50:use 20 COMMON18 ;AN000;"File cannot be copied onto itself"
51
52:def 21 "Invalid number of parameters",CR,LF ;AN000;
53
54:def 22 "Cannot XCOPY to a reserved device",CR,LF ;AN000;
55
56:use 23 EXTEND2 ;AN000;"File not found"
57
58:def 24 "File creation error",CR,LF ;AN000;
59
60:def 25 "Reading source file(s)...",CR,LF ;AN000;
61
62:def 26 CR,LF ;AN000;
63
64:def 27 "%1 File(s) copied",CR,LF ;AN000;
65
66:def 29 "F D " ;AN000;'PLEASE TRANSLATE' ELIMINATE THE SPACE CHARACTERS
67 ; FOR DBCS TRANSLATE. THIS TEXT IS USED TO COMPARE
68 ; THE RESPONSE OF F = FILE, D = DIRECTORY (MSG 4)
69
70:def 30 "%1%2",CR,LF ;AN000;S_PATH_FILE0
71
72:def 31 "%1\%2",CR,LF ;AN000;S_PATH_FILE1
73
74:def 32 "%1",CR,LF ;AN000;DISPLAY_S_PATH
75
76:def 33 "%1%2 (Y/N)?" ;AN000;P_S_PATH_FILE0
77
78:def 34 "%1\%2 (Y/N)?" ;AN000;P_S_PATH_FILE1
79
80:use 35 PARSE03 ;AC023;DUP SW ERROR MSG, 'INVALID SWITCH'
81
82:end ;AN000;
83;==========================================================
diff --git a/v4.0/src/CMD/XCOPY/XCOPYPAR.ASM b/v4.0/src/CMD/XCOPY/XCOPYPAR.ASM
new file mode 100644
index 0000000..b18aaf8
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/XCOPYPAR.ASM
@@ -0,0 +1,488 @@
1 PAGE ,132 ;
2 TITLE XCOPYPAR.SAL - LOOK AT COMMAND LINE PARMS
3;****************** START OF SPECIFICATIONS *****************************
4; MODULE NAME: XCOPYPAR.SAL
5;
6; DESCRIPTIVE NAME: Handle the definition of the DOS command line parameters
7; and the interface to the DOS system PARSER.
8;
9;FUNCTION: The static data areas are prescribed by the DOS system PARSER
10; to define the several parameters presented to XCOPY. These
11; data areas are passed to the PARSER, and its responses checked
12; to determine the nature of the user's specifications. Any errors
13; found in the user's parameters are defined in messages back
14; to the user.
15;
16; ENTRY POINT: PARSER, near
17;
18; INPUT: (DOS COMMAND LINE PARAMETERS)
19;
20; SOURCE OPERAND: TARGET OPERAND:
21;
22; [d:] [path] filename[.ext] [d:] [path] [filename[.ext]]
23; or
24; [d:] path [filename[.ext]]
25; or
26; d: [path] [filename[.ext]]
27;
28; WHERE
29;
30; [d:] - To specify the Source drive
31;
32; [d:] - To specify the Destination drive
33;
34;
35; SWITCHES:
36;
37; /A /D /E /M /P /S /V /W
38;
39;
40; Upon entry to PARSER in this module,
41; "CURRENT_PARM" = offset to start of parm text in command string
42; "ORDINAL" = initialized to zero
43; PSP+81H = text of DOS command line parms string
44
45; EXIT-NORMAL:
46
47; EXIT-ERROR:
48
49; INTERNAL REFERENCES:
50; ROUTINES:
51; PARSE_ERROR:NEAR Display the appropriate Parse error message.
52
53; DATA AREAS:
54; The several parameter control blocks, defined by the System
55; PARSER interface, defining the XCOPY parameters.
56
57; EXTERNAL REFERENCES:
58; ROUTINES:
59; SYSPARSE:NEAR System Command Line Common Parser.
60;
61; DATA AREAS:
62; EXITFL:BYTE Errorlevel return code.
63; MSGNUM_PARSE:WORD Message descriptor for all parse errors.
64;
65; NOTES:
66; This module should be processed with the SALUT preprocessor
67; with the re-alignment not requested, as:
68;
69; SALUT XCOPYPAR,NUL
70;
71; To assemble these modules, the alphabetical or sequential
72; ordering of segments may be used.
73;
74; For LINK instructions, refer to the PROLOG of the main module,
75; XCOPY.SAL.
76;
77; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
78; Ignore unique volume serial number differences
79; A004 PTM0700 9/02/87 Avoid duplicate switches and
80; display parm in error.
81;
82; Label: "The DOS XCOPY Utility"
83; "Version 4.00 (C)Copyright 1988 Microsoft"
84; "Licensed Material - Program Property of Microsoft "
85;
86;****************** END OF SPECIFICATIONS *****************************
87 IF1
88 %OUT COMPONENT=XCOPY, MODULE=XCOPYPAR.SAL...
89 ENDIF
90; = = = = = = = = = = = =
91HEADER MACRO TEXT
92.XLIST
93 SUBTTL TEXT
94.LIST
95 PAGE
96 ENDM
97; = = = = = = = = = = = =
98; $SALUT (4,23,28,36)
99; LOCAL EQUATES
100
101INIT_ERROR_FLAG EQU 80H ;AN000;critical initialization error. Should abort
102CMD_BUF_SIZE EQU 127 ;AN000;NUMBER BYTES IN DOS COMMAND LINE BUFFER
103ZERO EQU 0 ;AN000;COMPARAND FOR CLEARED REG
104NUL EQU 0 ;AN000;DELIMITER FOR ASCIIZ STRINGS
105
106; = = = = = = = = = = = =
107
108; PARSER ASSEMBLE SWITCHES
109
110FarSW EQU 0 ;AN000;CALL THE PARSER BY FAR CALL
111DateSW EQU 1 ;AN000;DATE FORMAT
112TimeSW EQU 1 ;AN000;TIME FORMAT
113FileSW EQU 1 ;AN000;FILE SPECIFICATION
114CAPSW EQU 1 ;AN000;USE FILE TABLE CAPS
115CmpxSW EQU 0 ;AN000;COMPLEX LIST
116DrvSW EQU 1 ;AN000;DRIVE ONLY FORMAT
117QusSW EQU 0 ;AN000;QUOTED STRING
118NumSW EQU 1 ;AN000;NUMERIC VALUE
119KeySW EQU 0 ;AN000;KEYWORDS
120SwSW EQU 1 ;AN000;SWITCHES
121Val1SW EQU 0 ;AN000;VALUE DEFINITION #1
122Val2SW EQU 0 ;AN000;VALUE DEFINITION #2
123Val3SW EQU 0 ;AN000;VALUE DEFINITION #3
124; = = = = = = = = = = = =
125; EXIT CODES FROM SYSPARSE (WHEN CY=0)
126
127SYSPRM_EX_OK EQU 0 ;AN000; no error
128SYSPRM_EX_MANY EQU 1 ;AN000; too many operands
129SYSPRM_EX_MISSING EQU 2 ;AN000; required operand missing
130SYSPRM_EX_NOT_SWLIST EQU 3 ;AN000; not in switch list provided
131SYSPRM_EX_NOT_KEYLIST EQU 4 ;AN000; not in keyword list provided
132SYSPRM_EX_RANGE EQU 6 ;AN000; out of range specified
133SYSPRM_EX_VALUE EQU 7 ;AN000; not in value list provided
134SYSPRM_EX_STRING EQU 8 ;AN000; not in string list provided
135SYSPRM_EX_SYNTAX EQU 9 ;AN000; syntax error
136SYSPRM_EX_EOL EQU -1 ;AN000; end of command line
137; = = = = = = = = = = = =
138
139 HEADER <STRUC - DEFINITIONS OF EXTERNAL CONTROL BLOCKS>
140; $SALUT (4,17,22,36)
141PSP STRUC
142 DB 80H DUP (?) ;AN000;SKIP OVER FIRST HALF OF PSP
143PSP_PARMLEN DB ? ;AN000;NUMBER OF BYTES IN DOS COMMAND LINE
144PSP_COMMAND DB 127 DUP(?) ;AN000;TEXT OF DOS COMMAND LINE
145PSP ENDS
146; = = = = = = = = = = = =
147CSEG SEGMENT PUBLIC ;AN000;PLACE HOLDER FOR PARSE CODE
148CSEG ENDS
149DGROUP GROUP DSEG, DSEG_INIT
150DSEG SEGMENT PARA PUBLIC
151DSEG ENDS
152;
153DSEG_INIT SEGMENT PARA PUBLIC
154;
155 INCLUDE PSDATA.INC ;AN018;WORK AREA USED BY PARSE.ASM
156;
157;--- EXTERNAL VARIABLES ---
158EXTRN PARM_FLAG: BYTE ;AN000;
159 IF1
160 %OUT COMPONENT=XCOPY, SUBCOMPONENT=PARSE
161 ENDIF
162;---
163COMMAND_LINE DB 127 DUP(?) ;AN000;TEXT OF DOS COMMAND LINE (INTERNAL USE)
164 PUBLIC COMMAND_LINE
165
166CURRENT_PARM DW DGROUP:COMMAND_LINE ;AN000;POINTER INTO COMMAND OF NEXT
167 ;OPERAND
168 PUBLIC CURRENT_PARM
169
170ORDINAL DW 0 ;AN000;ORDINAL NUMBER OF WHICH PARM TO PARSE
171 PUBLIC ORDINAL
172
173TAR_DRIVE DB " " ;AN000;TARGET DRIVE LETTER SPECIFIED IN PARMS
174SO_DRIVE DB " " ;AN000;SOURCE DRIVE LETTER SPECIFIED
175 PUBLIC TAR_DRIVE,SO_DRIVE ;AN000;PASS RESULTS TO INIT ROUTINE
176
177; = = = = = = = = = = = =
178 HEADER <DOS COMMAND LINE PARSER CONTROL BLOCKS>
179
180;INPUT PARAMETERS CONTROL BLOCK, POINTED TO BY ES:DI WHEN CALLING PARSER
181
182 PUBLIC PARMS ;AN000;LET LINK MAKE PARMS BLOCK ADDRESSABLE
183PARMS LABEL BYTE ;AN000;PARMS CONTROL BLOCK
184 DW DGROUP:PARMSX ;AN000;POINTER TO PARMS EXTENSION
185 DB 0 ;AN000; NUMBER OF STRINGS (0, 1, 2)
186 DB 1 ;AN000; NUMBER OF ADDITIONAL DELIMITERS
187 DB ";" ;AN000; ADDITIONAL DELIMITER
188
189
190;SYSTEM PARSER PARAMETER EXTENSION CONTROL BLOCK
191PARMSX LABEL BYTE ;AN000; PARMS EXTENSION CONTROL BLOCK
192 DB 1,2 ;AN000; MIN, MAX POSITIONAL OPERANDS ALLOWED
193 DW DGROUP:CONTROL_POS1 ;AN000; DESCRIPTION OF POSITIONAL 1
194 DW DGROUP:CONTROL_POS2 ;AN000; DESCRIPTION OF POSITIONAL 2
195
196 DB 2 ;AN000; THERE ARE 8 SWITCHES IN 2 GROUPS
197 ;AN000; (/A, /E, /M, /P, /S, /V, /W, /D)
198 DW DGROUP:SW1_7 ;AN000; POINTER TO THE SWITCH DEFINITION AREA
199 DW DGROUP:SW8 ;AN000; POINTER TO EIGHTH SWITCH DEFINITION AREA
200
201 DB 0 ;AN000; MAX KEYWORD OPERANDS ALLOWED
202 ;AN000; THERE IS NO CONTROL BLOCK
203 ;AN000; DEFINING KEYWORDS
204
205; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
206 HEADER <POSITIONAL PARM DESCRIPTOR BLOCK>
207;PARSER CONTROL BLOCK DEFINING THE ONLY POSITIONAL PARAMETER, OPTIONAL
208
209;FIRST POSITIONAL PARAMETER IS:
210;
211; [d:] [path] filename[.ext]
212; or
213; [d:] path [filename[.ext]]
214; or
215; d: [path] [filename[.ext]]
216;
217 PUBLIC CONTROL_POS1 ;AN000; LET LINK MAKE THIS ADDRESSABLE
218CONTROL_POS1 LABEL BYTE ;AN000; FIRST POSITIONAL DESCRIPTOR FOR FILESPEC
219 ;AN000;
220 DW 0200H ;AN000; CONTROLS TYPE MATCHED
221 ; SELECTED BITS: "FILE SPEC"
222
223 ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED)
224 ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE
225 ; CHECKED)
226 ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED)
227 ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED)
228 ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED)
229 ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED)
230 ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED)
231 ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED)
232 ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED)
233 ; 0010H=IGNORE ":" AT END IN MATCH
234 ; 0002H=REPEATS ALLOWED
235 ; 0001H=OPTIONAL
236
237 DW 0002H ;AN000; FUNCTION_FLAGS
238 ; 0001H=CAP RESULT BY FILE TABLE
239 ; 0002H=CAP RESULT BY CHAR TABLE
240 ; 0010H=REMOVE ":" AT END
241 DW DGROUP:RESULT1 ;AN000; RESULT BUFFER (FIRST)
242 PUBLIC RESULT1
243 DW DGROUP:NOVALS ;AN000; NO VALUE LISTS
244 DB 0 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS
245 ;AN000; IN FOLLOWING LIST
246
247;SECOND POSITIONAL PARAMETER IS:
248;
249; [d:] [path] [filename[.ext]]
250;
251 PUBLIC CONTROL_POS2 ;AN000; LET LINK MAKE THIS ADDRESSABLE
252CONTROL_POS2 LABEL BYTE ;AN000; SECOND POSITIONAL DESCRIPTOR FOR FILESPEC,
253 ;AN000; OPTIONAL
254 DW 0201H ;AN000; CONTROLS TYPE MATCHED
255 ;AN000; SELECTED BITS: "FILE SPEC"
256 DW 0002H ;AN000; FUNCTION_FLAGS
257 DW DGROUP:RESULT2 ;AN000; RESULT BUFFER (SECOND)
258 DW DGROUP:NOVALS ;AN000; NO VALUE LISTS
259 DB 0 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS
260 ;AN000; IN FOLLOWING LIST
261
262
263;VALUE CONTROL BLOCK FOR THE POSITIONAL PARAMETERS
264NOVALS DB 0 ;AN000;NO VALUE DEFINITIONS
265
266;RESULTS CONTROL BLOCK FOR THE FIRST POSITIONAL PARAMETER
267RESULT1 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS
268TYPE1 DB 0 ;AN000; TYPE RETURNED: 0=RESERVED,
269 PUBLIC TYPE1
270 ;AN000; 1=NUMBER, 2=LIST INDEX,
271 ;AN000; 3=STRING, 4=COMPLEX,
272 ;AN000; 5=FILESPEC, 6=DRIVE
273 ;AN000; 7=DATE, 8=TIME
274 ;AN000; 9=QUOTED STRING
275RESULT_TAG1 DB 0FFH ;AN000; MATCHED ITEM TAG
276 DW 0 ;AN000; POINTER TO SYNONYM
277
278RESULT_PTR1 DD 0 ;AN000; FILESPEC OFFSET
279 PUBLIC RESULT_PTR1
280
281;RESULTS CONTROL BLOCK FOR THE SECOND POSITIONAL PARAMETER
282RESULT2 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS
283 PUBLIC RESULT2
284TYPE2 DB 0 ;AN000; TYPE RETURNED: 0=RESERVED,
285 PUBLIC TYPE2
286 ;AN000; 1=NUMBER, 2=LIST INDEX,
287 ;AN000; 3=STRING, 4=COMPLEX,
288 ;AN000; 5=FILESPEC, 6=DRIVE
289 ;AN000; 7=DATE, 8=TIME
290 ;AN000; 9=QUOTED STRING
291RESULT_TAG2 DB 0FFH ;AN000; MATCHED ITEM TAG
292 DW 0 ;AN000; POINTER TO SYNONYM
293
294RESULT_PTR2 DD 0 ;AN000; FILESPEC OFFSET
295 PUBLIC RESULT_PTR2
296
297; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
298 HEADER <SWITCH PARM DESCRIPTOR BLOCK>
299;PARSER CONTROL BLOCK DEFINING THE SWITCHES, OPTIONAL
300
301 PUBLIC SW1_7 ;AN000;LET LINK MAKE THIS ADDRESSABLE
302SW1_7 LABEL BYTE ;AN000;SWITCH DESCRIPTOR FOR THE FIRST SEVEN SW
303 DW 0001H ;AN000; CONTROLS TYPE MATCHED
304 ;SELECTED BITS: "OPTIONAL"
305 ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED)
306 ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE
307 ; CHECKED)
308 ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED)
309 ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED)
310 ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED)
311 ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED)
312 ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED)
313 ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED)
314 ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED)
315 ; 0010H=IGNORE ":" AT END IN MATCH
316 ; 0002H=REPEATS ALLOWED
317 ; 0001H=OPTIONAL
318
319 DW 0002H ;AN000; FUNCTION_FLAGS
320 ; 0001H=CAP RESULT BY FILE TABLE
321 ; 0002H=CAP RESULT BY CHAR TABLE
322 ; 0010H=REMOVE ":" AT END
323
324 DW DGROUP:RESULTSW1 ;AN000; RESULT BUFFER
325 PUBLIC RESULTSW1 ;AN000;LET LINK MAKE THIS ADDRESSABLE
326 DW DGROUP:NOVALS ;AN000; VALUE LISTS
327 DB 7 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS
328 ;AN000; IN FOLLOWING LIST
329SW_A DB "/A",0
330 PUBLIC SW_A
331SW_E DB "/E",0
332 PUBLIC SW_E
333SW_M DB "/M",0
334 PUBLIC SW_M
335SW_P DB "/P",0
336 PUBLIC SW_P
337SW_S DB "/S",0
338 PUBLIC SW_S
339SW_V DB "/V",0
340 PUBLIC SW_V
341SW_W DB "/W",0
342 PUBLIC SW_W
343
344;PARSER CONTROL BLOCK DEFINING THE DATE SWITCH, OPTIONAL
345
346 PUBLIC SW8 ;AN000; LET LINK MAKE THIS ADDRESSABLE
347SW8 LABEL BYTE ;AN000; SWITCH DESCRIPTOR FOR THE DATE SW
348 DW 1000H ;AN000; CONTROLS TYPE MATCHED
349 DW 0000H ;AN000; FUNCTION_FLAGS
350 DW DGROUP:DATE_BUFF ;AN000; RESULT BUFFER
351 DW DGROUP:NOVALS ;AN000; VALUE LISTS
352 DB 1 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS
353 ;AN000; IN FOLLOWING LIST
354SW_D DB "/D",0
355 PUBLIC SW_D
356
357
358
359;RESULTS CONTROL BLOCK FOR THE /A,/E,/M,/P,/S,/V,/W SWITCHES
360RESULTSW1 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS
361 DB 3 ;AN000; TYPE RETURNED: 0=RESERVED,
362 ; 1=NUMBER, 2=LIST INDEX,
363 ; 3=STRING, 4=COMPLEX,
364 ; 5=FILESPEC, 6=DRIVE
365 ; 7=DATE, 8=TIME
366 ; 9=QUOTED STRING
367 DB 0FFh ;AN000; MATCHED ITEM TAG
368
369RESULTSWSYN DW 0 ;AN000; SYNONYM POINTER (BASED ON ES:)
370 PUBLIC RESULTSWSYN
371RESULTSWVAL DD 0 ;AN000; OFFSET OF STRING VALUE
372 PUBLIC RESULTSWVAL
373
374
375;RESULT CONTROL BLOCK FOR THE /D SWITCH
376DATE_BUFF LABEL BYTE
377 DB 7 ;AN000; TYPE RETURNED (DATE)
378 DB 0FFh ;AN000; MATCHED ITEM TAG
379 DW 0 ;AN000; SYNONYM POINTER (BASED ON ES:)
380DATE_YEAR DW 0 ;AN000; YEAR
381 PUBLIC DATE_YEAR
382DATE_MONTH DB 0 ;AN000; MONTH
383 PUBLIC DATE_MONTH
384DATE_DAY DB 0 ;AN000; DAY
385 PUBLIC DATE_DAY
386
387
388; = = = = = = = = = = = =
389DSEG_INIT ENDS
390 HEADER <PARSING WORKAREAS>
391; $SALUT (4,14,19,36)
392CSEG SEGMENT PUBLIC
393 ASSUME CS:CSEG, DS:DGROUP, ES:DGROUP
394
395 PUBLIC SYSPARSE ;AN000;SUBROUTINE ENTRY POINT ;AN000;
396
397
398 IF1
399 %OUT COMPONENT=XCOPY, SUBCOMPONENT=PARSE, MODULE=PARSE.ASM...
400 ENDIF
401INCSW EQU 0 ;AN018;TELL PARSE.ASM PSDATA.INC IS INCLUDED
402BASESW EQU 1 ;AN018;PSDATA.INC IS ADDRESSABLE WITH DS
403; INCLUDE PARSE.ASM ;AN000;GENERATED CODE SUPPRESSED FROM LISTING
404.XLIST
405.XCREF
406 INCLUDE PARSE.ASM
407.LIST
408.CREF
409
410 EXTRN GET_PARMS:NEAR ;AN000;COMMAND LINE PARMS AND OPTIONS PROCESSING
411
412 HEADER <PARSER - ASK SYSPARM TO DECODE PARAMETERS>
413; $SALUT (4,4,9,36)
414PARSER PROC NEAR
415 PUBLIC PARSER
416
417;INPUT: CURRENT_PARM = OFFSET TO NEXT PARM IN COMMAND STRING
418; COMMAND_LINE = COPY OF DOS COMMAND LINE PARAMETERS
419; "ORDINAL" = COUNT OF NEXT PARM TO PARSE
420;OUTPUT: CARRY IS SET IF THERE WAS A PROBLEM, AX HAS PARSE RET CODE.
421; CARRY IS CLEAR IF ALL OK WITH THE PARMS
422;THE PSP IS NOT REFERENCED, SINCE THE PARMS HAVE BEEN MOVED OUT OF THERE.
423
424
425 MOV ORDINAL,ZERO ;AN000;OPERAND ORDINAL, INITALLY ZERO
426; $SEARCH COMPLEX ;AN000;LOOP THRU COMMAND LINE
427 JMP SHORT $$SS1
428$$DO1:
429 ;AN000;LOOKING AT RETURN CODE IN AX,
430 ;AN000; JUST PRODUCED BY SYSPARSE...
431 CMP AX,ZERO ;AN000;WERE THERE ANY ERRORS?
432; $EXITIF NE,OR ;AN000;HAD A PROBLEM
433 JNE $$LL2
434 MOV ORDINAL,CX ;AN000;SAVE UPDATED COUNT
435 MOV CURRENT_PARM,SI ;AN000;REMEMBER HOW FAR I GOT
436 MOV BX,DX ;AN000;SET DATA BASE REG TO POINT TO THIS OPERAND
437 CALL GET_PARMS ;AN000;GET 1ST AND 2ND PARAMETERS
438 TEST PARM_FLAG,INIT_ERROR_FLAG ;AN000;CRITICAL PARAMETER ERROR HAS OCCURRED
439; $EXITIF NZ ;AN000;HAD A PROBLEM
440 JZ $$IF1
441$$LL2:
442 STC ;AN000;SET CARRY TO INDICATE ERROR
443 CALL PARM_ERROR ;AN000;GET OUT WITH ERROR INFORMATION
444 ;AN000;EITHER PARAMETER OR PARSER ERROR PROCESSED
445
446
447; $ORELSE ;AN000;SINCE NO PROBLEM, SO FAR
448 JMP SHORT $$SR1
449$$IF1:
450; $STRTSRCH
451$$SS1:
452
453 LEA DI,PARMS ;AN000; ES:DI = PARSE CONTROL DEFINITON
454 MOV SI,CURRENT_PARM ;AN000; DS:SI = COMMAND STRING, NEXT PARM
455 XOR DX,DX ;AN000; RESERVED, INIT TO ZERO
456 MOV CX,ORDINAL ;AN000; OPERAND ORDINAL, INITIALLY ZERO
457 CALL SYSPARSE
458 ;AN000; AX=EXIT CODE
459 ;AN000; BL=TERMINATED DELIMITER CODE
460 ;AN000; CX=NEW OPERAND ORDINAL
461 ;AN000; SI=SET TO PAST SCANNED OPERAND
462 ;AN000; DX=SELECTED RESULT BUFFER
463 CMP AX,SYSPRM_EX_EOL ;AN000; IS THAT THE END OF THE PARMS?
464 ;AN000;IF NOT, LOOP BACK AND FIND OUT
465 ;AN000; WHAT THAT PARM IS
466; $ENDLOOP E ;AN000;END OF LIST
467 JNE $$DO1
468 CLC ;AN000;CLEAR CARRY, END OF LIST OK
469; $ENDSRCH
470$$SR1:
471 RET ;AN000;RETURN TO CALLER
472PARSER ENDP
473; = = = = = = = = = = = =
474 HEADER <PARM_ERROR - ????????????>
475PARM_ERROR PROC NEAR
476;INPUT: DX - ADDRESS OF MESSAGE TEXT
477; PARM_FLAG set to INIT_ERROR_FLAG (critical error)
478; OR THERE WAS A PARSER ERROR
479
480 RET ;AN000;RETURN TO CALLER WITH C SET
481
482PARM_ERROR ENDP
483
484
485; = = = = = = = = = = = =
486CSEG ENDS
487 END
488 \ No newline at end of file
diff --git a/v4.0/src/CMD/XCOPY/XCPYINIT.ASM b/v4.0/src/CMD/XCOPY/XCPYINIT.ASM
new file mode 100644
index 0000000..33559ef
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/XCPYINIT.ASM
@@ -0,0 +1,1890 @@
1 PAGE ,132 ;
2TITLE XCPYINIT - XCOPY INITIALIZATION PROGRAM - Ver. 4.00
3
4;****************** START OF SPECIFICATIONS *****************************
5; MODULE NAME: XCPYINIT
6;
7; DESCRIPTIVE NAME: Called by XCOPY(MAIN) to perform initialization
8; functions.
9;
10; FUNCTION: Performs Parsing, Resource validation and Tagging, Error
11; hooking and then returns to XCOPY(MAIN). This code will
12; then be overwritten, providing additional memory for the
13; copy process.
14;
15; ENTRY POINT: INIT
16;
17; INPUT: (DOS COMMAND LINE PARAMETERS)
18;
19; SOURCE OPERAND: TARGET OPERAND:
20;
21; [d:] [path] filename[.ext] [d:] [path] [filename[.ext]]
22; or
23; [d:] path [filename[.ext]]
24; or
25; d: [path] [filename[.ext]]
26;
27; SWITCHES:
28;
29; /A /D /E /M /P /S /V /W
30;
31; EXIT-NORMAL: ERRORLEVEL_0 - This is the normal completion code.
32; ERRORLEVEL_2 - This is due to termination via Control-Break.
33; ERRORLEVEL_4 - This is used to indicate an error condition.
34;
35; INTERNAL REFERENCES:
36;
37; ROUTINES:
38;
39; DATA AREAS:
40;
41;
42; EXTERNAL REFERENCES:
43;
44; ROUTINES:
45;
46; DATA AREAS:
47;
48;
49; NOTES: This module should be processed with the SALUT pre-processor
50; with the re-alignment not requested, as:
51;
52; SALUT XCOPY,NUL,;
53;
54; To assemble these modules, the sequential
55; ordering of segments may be used.
56;
57; For LINK instructions:
58; link profile ..\lib
59;
60; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
61; Remove the BELL char.,turn off APPEND during TREE
62; search,Extended Attribute processing, Uppercasing
63; and "Out Of Space" during write to standard out.
64; NOTE: SEE XCOPY.SAL FOR TOTAL HISTORY.
65;
66; Label: "The DOS XCOPY Utility"
67; "Version 4.00 (C) Copyright 1988 Microsoft"
68; "Licensed Material - Program Property of Microsoft"
69;
70;****************** END OF SPECIFICATIONS *****************************
71;EQUATES
72INCLUDE XCOPY.EQU
73INCLUDE DOS.EQU
74include versiona.inc
75
76;
77CSEG SEGMENT PUBLIC ;PLACE HOLDER FOR INIT CODE
78CSEG ENDS
79
80;******************************************************************************
81
82DGROUP GROUP DSEG, DSEG_INIT
83DSEG SEGMENT PARA PUBLIC
84;--- EXTERNAL VARIABLES ---
85EXTRN ERRORLEVEL:BYTE
86EXTRN PSP_SEG:WORD ;PSP segment ** USE OF ES SHOULD BE EXAMINED FURTHER
87EXTRN SAV_DEFAULT_DRV:BYTE ;1 = A, 2 = B ...
88EXTRN SAV_DEFAULT_DIR:BYTE
89EXTRN SAV_S_DRV:BYTE
90EXTRN SAV_S_CURDIR:BYTE
91EXTRN SAV_T_DRV:BYTE
92EXTRN SAV_T_CURDIR:BYTE
93EXTRN TOP_OF_MEMORY:WORD
94EXTRN S_DRV_NUMBER:BYTE ;source drive number, 1 = A, 2 = B ...
95EXTRN T_DRV_NUMBER:BYTE ;target drive number
96EXTRN SO_DRIVE:BYTE ;AN000;S DRIVE LETTER SPECIFIED IN PARSE
97EXTRN S_DRV:BYTE
98EXTRN S_DRV_1:BYTE
99EXTRN S_DRV_PATH:BYTE ;formal source drv, path
100EXTRN S_PATH:BYTE
101EXTRN T_DRV_PATH:BYTE ;formal target drv, path
102EXTRN T_PATH:BYTE
103EXTRN TAR_DRIVE:BYTE ;AN000;T DRIVE LETTER SPECIFIED IN PARSE
104EXTRN PARMS:DWORD ;AN000;PARSER PARAMETER CONTROL BLOCK
105EXTRN CURRENT_PARM:WORD ;AN004;POINTER TO NEXT CMD LINE OPERAND
106EXTRN T_DRV:BYTE ;target drv letter
107EXTRN T_DRV_1:BYTE ;target drv letter
108EXTRN T_DRV_2:BYTE
109EXTRN S_FILE:BYTE ;source filename
110EXTRN T_FILENAME:BYTE
111EXTRN T_TEMPLATE:BYTE
112EXTRN DISP_S_PATH:BYTE ;input mirror image source path
113EXTRN DISP_T_PATH:BYTE ;input mirror image target path
114EXTRN BUFFER_PTR:WORD
115EXTRN BUFFER_BASE:WORD
116EXTRN BUFFER_LEFT:WORD
117EXTRN MAX_BUFFER_SIZE:WORD
118EXTRN MAX_CX:WORD
119EXTRN S_ARC_DRV:BYTE ;source drv, path for archieve bit handling
120EXTRN S_ARC_PATH:BYTE
121EXTRN T_MKDIR_LVL:BYTE ;# of target starting directories created.
122EXTRN MSG_NUM:WORD ;AN000;MESSAGE NUMBER
123EXTRN MSG_CLASS:BYTE ;AN000;MESSAGE CLASS
124EXTRN INPUT_FLAG:BYTE ;AN000;TYPE INT21 USED FOR KBD INPUT
125EXTRN SUBST_COUNT:WORD ;AN000;MESSAGE SUBSTITUTION COUNT
126EXTRN SUBLIST1:DWORD ;AN000;MSG SUBLIST USED BY INIT & MAIN
127;
128EXTRN MY_FLAG:BYTE
129EXTRN SYS_FLAG:BYTE
130EXTRN COPY_STATUS:BYTE
131EXTRN OPTION_FLAG:BYTE
132;
133EXTRN INPUT_DATE:WORD
134EXTRN INPUT_TIME:WORD
135;
136;
137DSEG ENDS
138;
139DSEG_INIT SEGMENT PARA PUBLIC ;AN000;
140;--- Local variables for INIT which will be free into memory after init.
141;----include file(s)------
142INCLUDE XINITMSG.EQU ;AN000;xcopy initialization, prompt msg
143;----variables------------
144S_INPUT_PARM DB 80 DUP (0) ;source image of input parm
145T_INPUT_PARM DB 80 DUP (0) ;target image of input parm
146T_TRANS_PATH DB 128 DUP (0) ;AN016;TARGET BUFFER FOR NAME TRANSLATE
147S_TRANS_PATH DB 128 DUP (0) ;AN016;SOURCE BUFFER FOR NAME TRANSLATE
148
149PUBLIC PARM_FLAG
150PARM_FLAG DB 0
151; first_parm_flag equ 01h ;first parm entered in input parm
152; second_parm_flag equ 02h ;second parm entered.
153; end_of_parm_flag equ 04h ;end of parm reached
154; copy_onto_itself_flag equ 08h ;copy onto itself flag
155; cyclic_flag equ 10h ;cyclic copy flag
156; inv_time_flag equ 20h ;invalid time
157; inv_date_flag equ 40h ;invalid date
158; init_error_flag equ 80h ;critical initialization error. Should abort.
159
160PARM1_FLAG DB 0
161; inv_s_path_flag equ 01h ;invalid source path (path not found)
162; inv_t_path_flag equ 02h ;invalid target path
163; s_file_flag equ 04h ;source filename entered
164; t_file_flag equ 08h ;target filename entered
165; INV_SW_flag equ 10h ;AN004;DUPLICATE OR INVALID SW ENTERED
166;
167TEMP_T_FILENAME DB 15 DUP (0) ;temporary target filename holder
168FILENAME_FOR_PROMPT DB 15 DUP (0) ;upper case lettered TEMP_T_FILENAME for prompts
169;** The following definitions are used for "Does ... specify a file name
170;** or directory name (F:file, D:directory)?.
171ALPHA_FILE DW ? ;AN000;THIS IS THE TRANSLATION OF 'F'
172ALPHA_DIR DW ? ;AN000;THIS IS THE TRANSLATION OF 'D'
173USER_INPUT DW ? ;AC000;KEYBOARD SAVE - MAY BE DBCS -
174
175Maxdays db 31,28,31,30,31,30,31,31,30,31,30,31 ;Max days per month
176Day db ? ;
177Month db ? ;
178Year dw ? ;
179Parmdate dw ? ;date parameter used in file date
180;
181COUNTRY_INFO DB 34 DUP (0)
182;-------------------------------
183; Structures
184;-------------------------------
185
186SUB_LIST STRUC ;AN000;MSG RETRIEVER SUBSTITUTION LST
187 DB 11 ;AN000;
188 DB 0 ;AN000;
189DATA_OFF DW 0 ;AN000; offset of data to be inserted
190DATA_SEG DW 0 ;AN000; offset of data to be inserted
191MSG_ID DB 0 ;AN000; n of %n
192FLAGS DB 0 ;AN000; Flags
193MAX_WIDTH DB 0 ;AN000; Maximum field width
194MIN_WIDTH DB 0 ;AN000; Minimum field width
195PAD_CHAR DB 0 ;AN000; character for pad field
196
197SUB_LIST ENDS ;AN000;
198
199DSEG_INIT ENDS
200;*******************************************************************************
201
202CSEG SEGMENT PUBLIC ;ATTACHED TO MAIN PROGRAM
203 ASSUME CS:CSEG, DS:DGROUP, ES:DGROUP
204;
205;--- PUBLIC PROCEDURES --- ;USED BY PARSER
206PUBLIC GET_PARMS ;AN000;
207;---------------------------
208
209;--- EXTERNAL PROCEDURES ---
210EXTRN SET_BUFFER_PTR:NEAR
211EXTRN STRING_LENGTH:NEAR
212EXTRN CONCAT_ASCIIZ:NEAR
213EXTRN LAST_DIR_OUT:NEAR
214EXTRN CHK_DBCS:NEAR ;AN010;NEEDED TO PARSE THE PATH STRING
215EXTRN COMPRESS_FILENAME:NEAR
216EXTRN CHK_DRV_LETTER:NEAR
217EXTRN SET_DEFAULT_DRV:NEAR
218EXTRN PRINT_STDOUT:NEAR
219EXTRN PRINT_STDERR:NEAR
220EXTRN MAIN_EXIT:NEAR
221EXTRN MAIN_EXIT_A:NEAR
222EXTRN CTRL_BREAK_EXIT:NEAR
223EXTRN PARSER:NEAR ;AN000;PROCESS THE KBD INPUT STRING
224EXTRN SYSGETMSG:NEAR ;AN000;TO GET THE 'F'ILE or 'D'IRECTORY
225EXTRN MY_INT24:WORD
226;---
227EXTRN SAV_INT24_OFF:WORD ;int 24, critical error handler addr.
228EXTRN SAV_INT24_SEG:WORD
229;
230;--- PARSER REFERENCES ---
231;
232EXTRN RESULT1:BYTE ;AN000;
233EXTRN RESULT_PTR1:DWORD ;AN000;
234EXTRN TYPE1:BYTE ;AN000;
235EXTRN RESULT2:BYTE ;AN000;
236EXTRN RESULT_PTR2:DWORD ;AN000;
237EXTRN TYPE2:BYTE ;AN000;
238EXTRN RESULTSW1:BYTE ;AN000;
239EXTRN RESULTSWSYN:WORD ;AN000;
240EXTRN SW_A:BYTE ;AN000;
241EXTRN SW_E:BYTE ;AN000;
242EXTRN SW_M:BYTE ;AN000;
243EXTRN SW_P:BYTE ;AN000;
244EXTRN SW_S:BYTE ;AN000;
245EXTRN SW_V:BYTE ;AN000;
246EXTRN SW_W:BYTE ;AN000;
247EXTRN SW_D:BYTE ;AN000;
248EXTRN DATE_YEAR:WORD ;AN000;
249EXTRN DATE_MONTH:BYTE ;AN000;
250EXTRN DATE_DAY:BYTE ;AN000;
251;---
252
253PUBLIC INIT
254INIT PROC NEAR
255 CMP AX, 0 ;check drv validity
256; $IF NE
257 JE $$IF1
258 MOV DX, MSG_INVALID_DRV ;AC000;GET THE MESSAGE ID
259 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error. Abort
260; $ELSE
261 JMP SHORT $$EN1
262$$IF1:
263 CALL HOOK_CTRL_BREAK ;hooks control break
264 CALL SAV_HOOK_INT24 ;hooks critical err handler
265 CALL GET_CUR_DRV ;save current default drv
266 MOV DL, SAV_DEFAULT_DRV
267 LEA SI, SAV_DEFAULT_DIR
268 CALL GET_CUR_DIR ;save current default dir
269 CALL PARSE_INPUT_PARM
270 TEST PARM_FLAG, INIT_ERROR_FLAG
271; $IF Z ;no error
272 JNZ $$IF3
273 CALL TOP_OF_MEM ;set top_of_memory
274 CALL INIT_BUFFER ;init buffer information
275
276 MOV DL, S_DRV_NUMBER
277 DEC DL
278 CALL SET_DEFAULT_DRV ;set source as a default drv
279; $ENDIF
280$$IF3:
281; $ENDIF
282$$EN1:
283 TEST PARM_FLAG, INIT_ERROR_FLAG ;any error?
284; $IF NZ ;yes. critical error
285 JZ $$IF6
286 CMP DX,MSG_INV_SW ;AN004;MSG REQUIRES SUB LIST
287; $IF NE,AND ;AC023;NO SUBLIST REQUIRED
288 JE $$IF7
289 CMP DX,MSG_INVALID_PARM ;AN004;MSG REQUIRES SUB LIST
290; $IF NE,AND ;AC023;NO SUBLIST REQUIRED
291 JE $$IF7
292 CMP DX,MSG_INV_NUM_PARM ;AN004;MSG REQUIRES SUB LIST
293; $IF NE ;AC023;NO SUBLIST REQUIRED
294 JE $$IF7
295 MOV SUBST_COUNT,NO_SUBST ;AN000;NO SUBSTITUTION TEXT
296 CMP DX,SYSPRM_MISSING_OP ;AN024;OPERANDS MISSING(2) ERR?
297; $IF E ;AN024;
298 JNE $$IF8
299 MOV DX,MSG_INV_NUM_PARM ;AN024;NO SUBLIST REQUIRED
300; $ENDIF ;AN024;
301$$IF8:
302 MOV MSG_NUM,DX ;AN000;NEED MESSAGE ID FOR PRINT
303; $ELSE ;AN004;SUBST LIST REQUIRED
304 JMP SHORT $$EN7
305$$IF7:
306 MOV MSG_NUM,DX ;AN004;NEED MESSAGE ID FOR PRINT
307 MOV SUBST_COUNT,PARM_SUBST_ONE ;AN004;PARM SUBST COUNT=1
308;
309 MOV DX,CURRENT_PARM ;AN004;OFFSET TO BAD SWITCH
310 LEA SI,SUBLIST1 ;AN004; address to sublist
311 MOV [SI].DATA_OFF,DX ;AN004; save data offset
312 MOV [SI].DATA_SEG,DS ;AN004; save data segment
313 MOV [SI].MSG_ID,0 ;AN023; message ID
314 MOV [SI].FLAGS,010H ;AN004; ASCIIZ str,l align
315 MOV [SI].MAX_WIDTH,0 ;AN004; MAXIMUM FIELD WITH
316 MOV [SI].MIN_WIDTH,0 ;AN004; MINIMUM FIELD WITH
317; $ENDIF ;AN004;
318$$EN7:
319 MOV INPUT_FLAG,NO_INPUT ;AN000;NO INPUT = 0
320 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
321 CALL PRINT_STDERR ;AN000;print error. AX point to msg ID
322 MOV ERRORLEVEL, 4 ;error ending
323 STC ;set carry and exit to the main_exit
324; $ELSE
325 JMP SHORT $$EN6
326$$IF6:
327 CLC
328; $ENDIF
329$$EN6:
330 RET
331INIT ENDP
332
333;
334PARSE_INPUT_PARM PROC NEAR
335;
336 CALL PARSER ;AN000;the PARSER interface routine
337; $IF C ;AC000;if no non_delimiter chr?
338 JNC $$IF14
339 TEST PARM_FLAG,INIT_ERROR_FLAG ;AN000;PARM ERR HAS OCCURRED
340; $IF Z ;AN000;NO, MUST BE PARSER ERROR
341 JNZ $$IF15
342 OR PARM_FLAG,INIT_ERROR_FLAG ;AN000;SET THE FLAG
343 CMP AX,SYSPRM_EX_MANY ;AN000;TOO MANY OPERANDS (1) ERR?
344; $IF E ;AN000;
345 JNE $$IF16
346 MOV BYTE PTR [SI],NUL ;AN024;DELIMIT BAD PARM
347 MOV DX,MSG_INV_NUM_PARM ;AN000;MSG NUM = 21
348; $ELSE ;AN000;
349 JMP SHORT $$EN16
350$$IF16:
351 CMP AX,SYSPRM_DUP_SW ;AN004;DUPLICATE SW REQUESTED
352; $IF E ;AN004;
353 JNE $$IF18
354 MOV BYTE PTR [SI],NUL ;AN004;DELIMIT BAD PARM
355 MOV DX,MSG_INV_SW ;AN004;MSG NUM = 35
356; $ELSE ;AN004;
357 JMP SHORT $$EN18
358$$IF18:
359 CMP AX,SYSPRM_MISSING_OP ;AN006;MISSING PARM=2
360; $IF E ;AN006;
361 JNE $$IF20
362 MOV DX,AX ;AN024 ;MSG NUM=21-NO SUBLIST
363; $ELSE ;AN006;
364 JMP SHORT $$EN20
365$$IF20:
366 MOV BYTE PTR [SI],NUL ;AN024;DELIMIT BAD PARM
367 MOV DX,MSG_INVALID_PARM ;AN000;MSG NUM = 3
368; $ENDIF ;AN006;
369$$EN20:
370; $ENDIF ;AN004;
371$$EN18:
372; $ENDIF ;AN000;
373$$EN16:
374; $ELSE ;AN006;INIT_ERROR_FLAG ALSO SET
375 JMP SHORT $$EN15
376$$IF15:
377 TEST PARM_FLAG,INV_DATE_FLAG ;AN006;WAS DATE INVALID?
378; $IF NZ ;AN006;THE DATE IS INVALID
379 JZ $$IF26
380 MOV DX,MSG_INVALID_DATE ;AN006;MSG NUM = 9
381; $ENDIF ;AN006;
382$$IF26:
383; $ENDIF ;AN000;
384$$EN15:
385; $ELSE ;AN000;
386 JMP SHORT $$EN14
387$$IF14:
388 CALL GET_DRIVES ;get source, target drive
389 TEST PARM_FLAG, INIT_ERROR_FLAG ;critical syntax error?
390; $IF Z ;if not,
391 JNZ $$IF30
392 CALL CHK_SLASH_W ;with /w, show "Press any key to begin ... " msg.
393 call save_for_display ;save source, target parm for display purposes
394 CALL CHK_SET_PARMS ;check and set each parms.
395 TEST PARM_FLAG, INIT_ERROR_FLAG ;critical syntax error?
396; $IF Z ;no
397 JNZ $$IF31
398 call modify_for_display ;set the source, target parm for display
399; $ENDIF
400$$IF31:
401; $ENDIF
402$$IF30:
403; $ENDIF
404$$EN14:
405 MOV AL, 0
406 LEA DI, S_PATH
407 CALL STRING_LENGTH ;cx - # of chr
408 LEA SI, S_PATH
409 LEA DI, S_ARC_PATH
410 REP MOVSB ;s_path => s_arc_path
411 RET
412PARSE_INPUT_PARM ENDP
413;
414
415CHK_SLASH_W PROC NEAR
416;if /W option is specified, then
417;show "Press any key to begin copying file(z)" message and wait for a key stroke.
418
419
420 TEST OPTION_FLAG, SLASH_W ;/W option taken?
421; $IF NZ ;yes.
422 JZ $$IF35
423 PUSH AX ;AN000;
424 MOV AX, MSG_TO_BEGIN ;AC000;GET THE MESSAGE ID
425 MOV MSG_NUM,AX ;AN000;SET THE MESSAGE NUMBER
426 MOV SUBST_COUNT,NO_SUBST ;AN000;NO SUBSTITUTION TEXT
427 MOV INPUT_FLAG,DOS_KEYB_INP ;AN000;RESPONSE EXPECTED = 1
428 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
429 CALL PRINT_STDOUT ;AN000;MSG AX points to message ID
430
431 MOV AX,MSG_CR_LF_STR ;AN000; JUST CR,LF
432 MOV MSG_NUM,AX ;AN000; set message number
433 MOV INPUT_FLAG,NO_INPUT ;AN000; NO INPUT
434 CALL PRINT_STDOUT ;AN000; Display message
435
436 POP AX ;AN000;
437; $ENDIF
438$$IF35:
439 RET
440
441CHK_SLASH_W ENDP
442;
443PROMPT_TO_USER PROC NEAR
444;guide the user to enter the input parameters
445;get user input to S_INPUT_PARM, T_INPUT_PARM for source, target parms.
446;INPUT: ES - PSP seg
447; DS - data seg
448; SAV_DEFAULT_DRV
449;
450 MOV dx, msg_inv_num_parm ;AC000;GET THE MESSAGE ID
451 or parm_flag, init_error_flag
452 RET
453PROMPT_TO_USER ENDP
454;
455GET_PARMS PROC NEAR
456;Get the first parameter(s), second parameter(s) and option(s).
457;Not checking correct character entered.
458;The logic is:
459;1). Find the first non_delim from the Parser control block. This is the
460; start of the first parm. Validate the length and put into S_INPUT_PARM.
461; Note that this routine currently does not check the S_INPUT_PARM to see
462; if it is valid or not.
463;2). Find the next non_delim from the Parser control block. This is the
464; start of the second parm. Validate the length and put into T_INPUT_PARM.
465; Note that this routine currently does not check the T_INPUT_PARM to see
466; if it is valid or not.
467;3). Find the switch(es) from the parser control block and set the
468; corresponding bit in the option flag word(OPTION_FLAG) by calling
469; GET_OPTIONS.
470;
471;INPUT:
472; BX - PARSER OPERAND POINTER
473
474 PUSH DS ;AN000;
475 CMP BX,OFFSET DGROUP:RESULT1 ;AN000;WAS FIRST FILESPEC SPECIFIED?
476; $IF E ;AN000;IF FIRST FILESPEC SPECIFIED,
477 JNE $$IF37
478 LDS SI,RESULT_PTR1 ;AN000;GET WHERE THE STRING IS
479 ASSUME DS:NOTHING ;AN000;
480 CMP DS:BYTE PTR [SI]+BYTE,COLON ;AN000;DOES FILESPEC START WITH
481 ;DRIVE?
482; $IF E ;AN000;STARTS WITH DRIVE
483 JNE $$IF38
484 LODSW ;AN000;GET JUST THE DRIVE LETTER AND
485 MOV ES:SO_DRIVE,AL ;AN000;ALSO ADJUSTS WHERE THE STRING IS
486 LEA DI,ES:S_INPUT_PARM ;AN000;MOVE PARM TO SOURCE FILESPEC
487 STOSW ;AN000;MOVE DRIVE TO FILESPEC
488; $ELSE ;AN000;DOES NOT START WITH DRIVE
489 JMP SHORT $$EN38
490$$IF38:
491 LEA DI,ES:S_INPUT_PARM ;AN000;MOVE PARM TO SOURCE FILESPEC
492; $ENDIF ;AN000;FILESPEC HAVE DRIVE?
493$$EN38:
494 CMP DGROUP:TYPE1,5 ;AN000;FILESPEC ?
495; $IF E ;AN000;MORE THAN JUST DRIVE
496 JNE $$IF41
497 ;MOVE PARM TO WHERE FIND FIRST/NEXT
498 ; WILL KNOW WHERE TO START
499 PUSH BX ;AN000;SAVE THE DATABASE POINTER
500 XOR BX,BX ;AN000;ZERO FOR THE PARAMETER LENGTH
501; $DO COMPLEX ;AN000;
502 JMP SHORT $$SD42
503$$DO42:
504 INC BX ;AN000;CALCULATE LENGTH
505 STOSB ;AN000;MOVE CHAR TO FILESPEC
506; $STRTDO ;AN000;
507$$SD42:
508 LODSB ;AN000;GET NEXT CHAR FROM COMMAND LINE
509 CMP AL,NUL ;AN000;IS THAT THE END OF THE STRING
510; $ENDDO E ;AN000;GOT IT ALL, QUIT
511 JNE $$DO42
512 CALL CHK_MAX_LENGTH ;AN000;LENGTH OF STRING <=64
513 POP BX ;AN000;RESTORE THE DATA BASE POINTER
514; $IF NC ;no, less than or equal
515 JC $$IF45
516 OR PARM_FLAG, FIRST_PARM_FLAG
517; $ELSE ;AN000;
518 JMP SHORT $$EN45
519$$IF45:
520 MOV DX, MSG_LONG_PATH ;AN000;ADDRESS OF MESSAGE TXT
521 OR PARM_FLAG, INIT_ERROR_FLAG ;AN000;
522; $ENDIF ;AN000;CRITICAL ERROR INDICATED
523$$EN45:
524; $ENDIF ;AN000;MOVE ALL DONE
525$$IF41:
526; $ELSE ;AN000;IF SECOND FILESPEC SPECIFIED,
527 JMP SHORT $$EN37
528$$IF37:
529 CMP BX,OFFSET DGROUP:RESULT2 ;AN000;WAS 2nd FILESPEC SPECIFIED?
530; $IF E ;AN000;IF SECOND FILESPEC SPECIFIED
531 JNE $$IF50
532 LDS SI,RESULT_PTR2 ;AN000;GET WHERE THE STRING IS
533 ASSUME DS:NOTHING ;AN000;
534 CMP DS:BYTE PTR [SI]+BYTE,COLON ;AN000;DOES FILESPEC START
535 ;WITH DRIVE?
536; $IF E ;AN000;STARTS WITH DRIVE
537 JNE $$IF51
538 LODSW ;AN000;GET JUST THE DRIVE LETTER AND
539 MOV ES:TAR_DRIVE,AL ;AN000;ALSO ADJUSTS WHERE THE STRING IS
540 LEA DI,ES:T_INPUT_PARM ;AN000;MOVE PARM TO TARGET FILESPEC
541 STOSW ;AN000;MOVE DRIVE TO FILESPEC
542; $ELSE ;AN000;DOES NOT START WITH DRIVE
543 JMP SHORT $$EN51
544$$IF51:
545 LEA DI,ES:T_INPUT_PARM ;AN000;MOVE PARM TO TARGET FILESPEC
546; $ENDIF ;AN000;FILESPEC HAVE DRIVE?
547$$EN51:
548 CMP DGROUP:TYPE2,5 ;AN000;FILESPEC ?
549; $IF E ;AN000;MORE THAN JUST DRIVE
550 JNE $$IF54
551 ;AN000;MOVE PARM TO WHERE FIND FIRST/NEXT
552 ;AN000; WILL KNOW WHERE TO START
553 PUSH BX ;AN000;SAVE THE DATABASE POINTER
554 XOR BX,BX ;AN000;ZERO FOR THE PARAMETER LENGTH
555; $DO COMPLEX ;AN000;
556 JMP SHORT $$SD55
557$$DO55:
558 INC BX ;AN000;CALCULATE LENGTH
559 STOSB ;AN000;MOVE CHAR TO FILESPEC
560; $STRTDO ;AN000;
561$$SD55:
562 LODSB ;AN000;GET NEXT CHAR FROM COMMAND LINE
563 CMP AL,NUL ;AN000;IS THAT THE END OF THE STRING
564; $ENDDO E ;AN000;GOT IT ALL, QUIT
565 JNE $$DO55
566 CALL CHK_MAX_LENGTH ;AN000;LENGTH OF STRING <=64
567 POP BX ;AN000;RESTORE THE DATA BASE POINTER
568; $IF NC
569 JC $$IF58
570 OR PARM_FLAG, SECOND_PARM_FLAG
571; $ELSE
572 JMP SHORT $$EN58
573$$IF58:
574 MOV DX, MSG_LONG_PATH ;AN000;ADDRESS OF MESSAGE TXT
575 OR PARM_FLAG, INIT_ERROR_FLAG ;AN000;
576; $ENDIF ;AN000;CRITICAL ERROR INDICATED
577$$EN58:
578; $ENDIF ;AN000;SECOND FILESPEC
579$$IF54:
580; $ELSE ;AN000;FILESPEC NOT SPECIFIED
581 JMP SHORT $$EN50
582$$IF50:
583 CALL GET_OPTIONS ;AN000;PROCESS THE SWITCHES
584; $ENDIF ;AN000;MOVE ALL DONE
585$$EN50:
586; $ENDIF ;AN000;FILESPEC?
587$$EN37:
588 POP DS ;AN000;
589 ASSUME DS:DGROUP ;AN000;
590 RET
591GET_PARMS ENDP
592;
593SAVE_FOR_DISPLAY PROC NEAR
594;save first parm, second parm into DISP_S_PATH, DISP_T_PATH.
595;at this time, this is not gauranteed to be a path. They may
596;contains filename in it.
597;input: S_INPUT_PARM, T_INPUT_PARM, PARM_FLAG
598; DS: data seg
599; ES: psp
600
601 PUSH ES ;save ES
602 PUSH DS
603 POP ES ;ES = DS
604 TEST PARM_FLAG, FIRST_PARM_FLAG ;first parm entered?
605; $IF NZ ;yes
606 JZ $$IF65
607 MOV AL, 0 ;asciiz
608 LEA DI, S_INPUT_PARM
609 CALL STRING_LENGTH ;now CX has length
610 LEA SI, S_INPUT_PARM
611 LEA DI, DISP_S_PATH ;source path for display
612 CALL MOV_STRING ;AC000;s_input_parm => disp_s_path
613
614; $ENDIF
615$$IF65:
616 TEST PARM_FLAG, SECOND_PARM_FLAG ;second parm entered?
617; $IF NZ
618 JZ $$IF67
619 MOV AL, 0
620 LEA DI, T_INPUT_PARM
621 CALL STRING_LENGTH
622 LEA SI, T_INPUT_PARM
623 LEA DI, DISP_T_PATH
624 CALL MOV_STRING ;AC000;s_input_parm => disp_s_path
625; $ENDIF
626$$IF67:
627 POP ES
628 RET
629SAVE_FOR_DISPLAY ENDP
630;
631MOV_STRING PROC NEAR ;AN000;
632; move string from DS:SI to ES:DI
633; CX should indicate string length
634 cld
635; $DO
636$$DO69:
637 CMP CX, 0
638; $LEAVE Z
639 JZ $$EN69
640 LODSB ;[si] => AL
641 STOSB ;AL => [di]
642 DEC CX
643; $ENDDO
644 JMP SHORT $$DO69
645$$EN69:
646 RET
647MOV_STRING ENDP ;AN000;
648;
649MODIFY_FOR_DISPLAY PROC NEAR
650;finally trims DISP_S_PATH, DISP_T_PATH into good shape.
651;input: DS, ES = data seg. S_FILE_FLAG, T_FILE_FLAG
652
653 LEA DI, DISP_S_PATH
654 LEA SI, DISP_S_PATH
655 TEST PARM1_FLAG, S_FILE_FLAG ;source filename entered?
656 JZ MFD_NO_FILE1 ;no
657 CALL MASSAGE_DISP_PATH ;yes, entered.
658 JMP SHORT MFD_TARGET
659MFD_NO_FILE1: ;no source filename
660 CALL CHK_DRV_LETTER ;using [si]
661 JC MFD_CHK_TAIL1
662 CMP BYTE PTR [SI], 0 ;D:,0 case
663 JE MFD_TARGET ;OK
664 CMP BYTE PTR [SI], '\'
665 JNE MFD_CHK_TAIL1 ;D:dir... case
666 CMP BYTE PTR [SI+1], 0 ;D:\,0 case
667 JE MFD_TARGET ;OK
668MFD_CHK_TAIL1: ;else check tail
669 CALL CHK_TAIL_CHR ;chk tail and put \ at the end. using di
670MFD_TARGET:
671 LEA DI, DISP_T_PATH
672 LEA SI, DISP_T_PATH
673 TEST PARM1_FLAG, T_FILE_FLAG
674 JZ MFD_NO_FILE2
675 CALL MASSAGE_DISP_PATH
676 JMP SHORT MFD_EXIT
677MFD_NO_FILE2:
678 CALL CHK_DRV_LETTER
679 JC MFD_CHK_TAIL2
680 CMP BYTE PTR [SI], 0
681 JE MFD_EXIT
682 CMP BYTE PTR [SI], '\'
683 JNE MFD_CHK_TAIL2
684 CMP BYTE PTR [SI+1], 0
685 JE MFD_EXIT
686MFD_CHK_TAIL2:
687 CALL CHK_TAIL_CHR
688MFD_EXIT:
689 RET
690MODIFY_FOR_DISPLAY ENDP
691;
692CHK_TAIL_CHR PROC NEAR
693;check the last chr of ASCIIZ string pointed by DI.
694;if it is \,0 then OK, else put \ there.
695;DS, ES = data seg
696;DI points to string.
697;OUTPUT: Revised string.
698;AX, BX, CX - destroyed
699 MOV AL, 0 ;asciiz
700 PUSH DI ;save di
701 CALL STRING_LENGTH ;now cx got the length including 0
702 POP DI ;restore di
703 DEC CX
704 DEC CX
705 MOV BX, CX
706 CMP BYTE PTR [DI][BX], '\' ;last chr before 0
707 JE CTC_EXIT ;\,0 case
708 MOV BYTE PTR [DI][BX+1], '\' ;change 0 to '\'
709 MOV BYTE PTR [DI][BX+2], 0 ;make it asciiz again.
710CTC_EXIT:
711 RET
712CHK_TAIL_CHR ENDP
713;
714MASSAGE_DISP_PATH PROC NEAR
715;INPUT: DS, ES = data seg
716; DI = points to source. Used for LAST_DIR_OUT
717; SI = points to source. Used for CHK_DRV_LETTER routine
718;OUTPUT: Revised source string
719
720 CALL LAST_DIR_OUT
721; $IF C ;failure? no '\' found
722 JNC $$IF72
723 CALL CHK_DRV_LETTER ;drive letter?
724; $IF NC ;yes. "D:filename",0 case
725 JC $$IF73
726 MOV BYTE PTR DS:[SI], 0 ;make it "D:",0 since SI now points to the next chr
727; $ELSE ;no. "filename",0 case
728 JMP SHORT $$EN73
729$$IF73:
730 MOV BYTE PTR [DI], 0 ;set DISP_S_PATH to 0
731; $ENDIF
732$$EN73:
733; $ELSE ;found '\' and last '\' became 0
734 JMP SHORT $$EN72
735$$IF72:
736 MOV DI, AX ;we want to restore '\' and put 0 just after that.
737 DEC DI ;for ex, "D:\filename"=>"D:"=>"D:\"
738 MOV BYTE PTR [DI], '\' ; "D:dir1\dir2"=>"D:dir1"=>"D:dir1\"
739 MOV BYTE PTR [DI+1], 0
740; $ENDIF
741$$EN72:
742 RET
743MASSAGE_DISP_PATH ENDP
744;
745CHK_MAX_LENGTH PROC NEAR
746;Check the length of the source or target input string although this does not
747;gaurantee the validity of the length of path. This will just check/reduce
748;the possibilities of long path.
749;If the path string is longer than 64 (this includes 0 at the end of the string)
750;then, carry will be set.
751;INPUT: ds - data seg
752; es - psp seg
753; SI - points to the starting chr of the string.
754; BX - length of the string
755;OUTPUT:
756; carry will set if the length if longer than we expected.
757
758 PUSH BX ;AN000;
759 PUSH DI
760 PUSH SI
761 ;AC001;DELETED CODE FOR PTM0011
762 CMP BYTE PTR [SI], '\' ;SI points to '\'?
763 JNE CML_LENGTH ;no, now compare the length
764 DEC BX ;AC000;decrease length by 1 for '\'
765CML_LENGTH:
766 CMP BX, 63 ;AC000;length of string > 63?
767 JG CML_CARRY ;AC027;WORK WITH ONLY + CMP RESULT
768 CLC ;NO. OK.
769 JMP CML_EXIT
770CML_CARRY:
771 STC ;not OK
772CML_EXIT:
773 POP SI
774 POP DI
775 POP BX ;AN000;
776 RET
777
778CHK_MAX_LENGTH ENDP
779;
780;
781GET_OPTIONS PROC NEAR
782;get options from the PARSER and
783;set OPTION_FLAG.
784;INPUT:
785; BX - PARSER OPERAND POINTER
786;
787 CMP BX,OFFSET DGROUP:RESULTSW1 ;AN000;WAS SW 1 THROUGH 7 SPECIFIED?
788 MOV DI,RESULTSWSYN ;AN000;GET THE SYNONYM POINTER [ES]
789
790; $IF E,LONG ;AN000;IF SWITCH SPECIFIED
791 JE $$XL1
792 JMP $$IF78
793$$XL1:
794 CMP BYTE PTR ES:[DI+BYTE],ALPHA_S ;AC000;"S"
795 JNE GO_A
796 OR OPTION_FLAG, SLASH_S ;set the walk the tree bit on.
797 MOV SW_S,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
798 JMP GO_EXIT ;AC000;
799GO_A:
800 CMP BYTE PTR ES:[DI+BYTE],ALPHA_A ;AN000;"A"
801 JNE GO_M
802 MOV SW_A,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
803 TEST OPTION_FLAG, SLASH_M ;hard archieve already on?
804 JZ GO_A1 ;if not, continue
805 AND OPTION_FLAG, RESET_SLASH_M ;else turn it off
806GO_A1:
807 OR OPTION_FLAG, SLASH_A ;set soft archieve
808 JMP GO_EXIT ;AC000;
809GO_M:
810 CMP BYTE PTR ES:[DI+BYTE],ALPHA_M ;AN000;"M"
811 JNE GO_P
812 MOV SW_M,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
813 TEST OPTION_FLAG, SLASH_A ;soft archieve already on?
814 JZ GO_M1 ;if not, skip this part
815 AND OPTION_FLAG, RESET_SLASH_A ;else turn off the soft archieve bit
816GO_M1:
817 OR OPTION_FLAG, SLASH_M ;turn on the hard archieve bit.
818 JMP GO_EXIT ;AC000;
819GO_P:
820 CMP BYTE PTR ES:[DI+BYTE],ALPHA_P ;AN000;"P"
821 JNE GO_E
822 MOV SW_P,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
823 OR OPTION_FLAG, SLASH_P
824 OR MY_FLAG, SINGLE_COPY_FLAG ;if user want prompt, then should be single copy (not a multi copy).
825 JMP SHORT GO_EXIT ;AC000;
826GO_E:
827 CMP BYTE PTR ES:[DI+BYTE],ALPHA_E ;AN000;"E"
828 JNE GO_V
829 MOV SW_E,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
830 OR OPTION_FLAG, SLASH_E ;turn on "creating empty dir" bit.
831 JMP SHORT GO_EXIT ;AC000;
832GO_V:
833 CMP BYTE PTR ES:[DI+BYTE],ALPHA_V ;AN000;"V"
834 JNE GO_W
835 MOV SW_V,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
836 MOV AH, 54h ;get verify setting
837 INT 21H
838 CMP AL, 0
839 JNE GO_EXIT ;AC000;if not 0, then already on.
840 MOV AX, 2E01h ;else set it on
841 INT 21h
842 OR SYS_FLAG, TURN_VERIFY_OFF_FLAG ;don't forget it off when exit to dos.
843 JMP SHORT GO_EXIT ;AC000;
844GO_W:
845 OR OPTION_FLAG, SLASH_W
846 MOV SW_W,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
847 JMP SHORT GO_EXIT ;AC000;
848; $ELSE ;AN000;SINCE SWITCH 1 - 7 NOT SPECIFIED
849 JMP SHORT $$EN78
850$$IF78:
851 ; IT MUST BE THE DATE SWITCH
852 CALL GET_INPUT_DATE ;AN000;get date from parser control block
853 OR OPTION_FLAG, SLASH_D
854 MOV SW_D,SPACE ;AN004;DISALLOW DUPLICATE SWITCHES
855; $ENDIF ;AN000;
856$$EN78:
857GO_EXIT:
858 RET
859GET_OPTIONS ENDP
860
861GET_INPUT_DATE PROC NEAR
862;get the input date from the parser and save it to INPUT_DATE form which
863;it can be used for comparison with FILE_DATE_DTA.
864;INPUT:
865;
866;
867;OUTPUT:
868;
869;
870;
871
872 CALL VALIDATE_INPUT_DATE ;AN006;GO CHECK THE DATE
873; $IF C ;AN006;SET IF THE DATE WAS INVALID
874 JNC $$IF81
875 OR PARM_FLAG,INV_DATE_FLAG ;AN006;SET THE FLAG FOR DATE ERROR
876 OR PARM_FLAG,INIT_ERROR_FLAG ;AN006;SET THE FLAG FOR ERROR
877; $ELSE ;AN006;DATE WAS OK
878 JMP SHORT $$EN81
879$$IF81:
880 MOV AX,DATE_YEAR ;AN000;GET YEAR FROM PARSER CTRL BLOCK
881 SUB AX,1980 ;AN000;SUBTRACT THE BASE YEAR
882 mov cl,4 ;AN000;SHIFT REG COUNT = 4
883 shl ax,cl ;AN000;Shift it over 4
884 xor dh,dh ;AN000;CLEAR THE AREA
885 mov dl,DATE_MONTH ;AN000;GET MONTH FROM PARSER CTRL BLOCK
886 add ax,dx ;AN000;Add in the Month
887 inc cl ;AN000;BUMP SHIFT COUNT
888 shl ax,cl ;AN000;Shift it over 5
889 xor dh,dh ;AN000;CLEAR THE AREA
890 mov dl,DATE_DAY ;AN000;GET DAY FROM PARSER CTRL BLOCK
891 add ax,dx ;AN000;Add in the Day
892 mov INPUT_DATE,ax ;AN000;Store the date in DOS FCB format
893 CLC ;AN000;CLEAR THE CARRY
894; $ENDIF ;AN006;
895$$EN81:
896 RET
897GET_INPUT_DATE ENDP
898;
899VALIDATE_INPUT_DATE PROC NEAR
900;CHECK FOR VALID DATE.
901;
902;OUTPUT: INVALID DATE = CARRY SET
903;
904;
905;
906;
907 MOV AH,GET_DATE ;AN006;DOS INT 2AH
908 INT 21H ;AN006;MAKE THE CALL
909 PUSH CX ;AN006;YEAR
910 PUSH DX ;AN006;MONTH,DAY
911 MOV AH,SET_DATE ;AN006;DOS INT 2BH
912 MOV CX,DATE_YEAR ;AN006;GET YEAR FROM PARSER CTL BLOCK
913 MOV DH,DATE_MONTH ;AN006;GET MONTH FROM PARSER CTL BLOCK
914 MOV DL,DATE_DAY ;AN006;GET DAY FROM PARSER CTL BLOCK
915 INT 21H ;AN006;MAKE THE CALL
916 POP DX ;AN006;GET THE SYSTEM MONTH,DAY
917 POP CX ;AN006;GET THE SYSTEM YEAR
918 OR AL,AL ;AN006;WAS MY INPUT DATE VALID?
919 STC ;AN006;SET THE CARRY
920 JNZ ERR_DATE ;AN006;GET OUT WITH C SET
921 CLC ;AN006;CLEAR THE CARRY, NO ERROR
922 MOV AH,SET_DATE ;AN006;RESTORE THE SYSTEM DATE
923 INT 21H ;AN006;MAKE THE CALL
924ERR_DATE: ;AN006;
925 RET ;AN006;
926;
927VALIDATE_INPUT_DATE ENDP
928;
929CHK_SET_PARMS PROC NEAR
930;This does a semantic checking on the given S_INPUT_PARM, T_INPUT_PARM and
931;sets each of the starting drv path into S_PATH, T_PATH.
932;The basic logic is:
933;1). Try to change dir to a given S_INPUT_PARM.
934; if a success, then it must be the path. Chdir to it and get current
935; source directory using S_DRV_NUMBER by issuing GET_Current_directory call,
936; which starts from the root of the source drive. In this way, you don't
937; have to worry about what type of path for the source has been entered.
938; You just try to chdir according to S_INPUT_PARM and
939; then call get_cur_dir to get the S_PATH which will always start
940; from the root of the source drive.
941; if not, then there must be the filename at the end, or there might be
942; garbage in the path. So, take the last path name (which is, hopely,
943; a filename) and try chdir again. If a success, then current source dir
944; is determined. Otherwise, error. Issue "Invalid direcory name". If a
945; success, then check the saved filename to make sure that there are no
946; invalid chr's in it. (When you try to take the last_dir_out, and
947; it has failed (carry set), then it was a filename candidate itself
948; (sometimes together with an drive id d:). In this case, you have to
949; check the filename candidate if it has a drive id in front of it.
950; if it is, then take the drive id d: off from it and reshape the
951; filename candidate. And check the invalid characters if any. Of cause
952; in this case, current direcory of source drv becomes S_PATH.
953;2). Try to change dir to a given T_INPUT_PARM, if any. (If no T_INPUT_PARM
954; entered, then set current directory to the starting path of target using
955; T_DRV_NUMBER.)
956; If a success, then no problem. It is a strating target path.
957; If not, then take the last dir out and try again. If a failure, then
958; error "Invalid directory".
959; If a success, then check the saved filename to see if any illigal
960; characters in it. If they are, then error. Else issue fun.29h
961; to see if there are any global characters in it. If there
962; are, then assume a filename. If there are not, then ask user
963; "Is XXXXX a filename in the target? (n)" If no, then it is a
964; subdirectory name. Make a new subdirectory in the target and
965; concatenate a new directory name to the T_INPUT_PARM and chdir to
966; the new path (, which is the original path in fact) again.
967;INPUT:
968; ES - PSP seg ; this will be changed to DS within this routine
969; DS - data seg
970
971 PUSH DS
972 POP ES ;set ES to DS
973 TEST PARM_FLAG, FIRST_PARM_FLAG ;first parm entered?
974; $IF Z,AND ;NO
975 JNZ $$IF84
976 TEST PARM_FLAG, SECOND_PARM_FLAG ;second parm entered?
977; $IF Z ;NO
978 JNZ $$IF84
979 MOV DX, MSG_INV_NUM_PARM ;AC000;GET THE MESSAGE ID
980 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error. exit program
981; $ELSE
982 JMP SHORT $$EN84
983$$IF84:
984
985 MOV DL, S_DRV_NUMBER
986 LEA SI, SAV_S_CURDIR
987 CALL GET_CUR_DIR ;get and save current source directory
988 OR SYS_FLAG, DEFAULT_S_DIR_FLAG ;indicates source dir saved
989 TEST PARM_FLAG, FIRST_PARM_FLAG ;first parm only entered?
990; $IF Z ;no first parm
991 JNZ $$IF86
992 LEA SI, S_PATH ;then make current source dir as S_PATH
993 CALL GET_CUR_DIR
994; $ELSE ;else first parm entered. check it
995 JMP SHORT $$EN86
996$$IF86:
997 LEA DX, S_INPUT_PARM ;try to chdir to S_INPUT_PARM
998 MOV AH, Chdir ;= 3Bh
999 INT 21h
1000; $IF NC ;success?
1001 JC $$IF88
1002 MOV DL, S_DRV_NUMBER
1003 LEA SI, S_PATH ;get current dir and save it
1004 CALL GET_CUR_DIR ;as a starting dir to S_PATH
1005; $ELSE
1006 JMP SHORT $$EN88
1007$$IF88:
1008 LEA BX, S_INPUT_PARM
1009 LEA DX, S_FILE ;source filename
1010 CALL TAKE_PATH_TAIL ;take out the tail part of S_INPUT_PARM
1011 LEA DX, S_INPUT_PARM
1012 MOV AH, Chdir ;= 3Bh
1013 INT 21h ;try chdir again
1014; $IF NC,AND ;success?
1015 JC $$IF90
1016 CMP S_FILE, 0 ;check s_file if something is there
1017; $IF NE ;yes, filename entered.
1018 JE $$IF90
1019 MOV DL, S_DRV_NUMBER
1020 LEA SI, S_PATH
1021 CALL GET_CUR_DIR ;save current dir
1022 OR PARM1_FLAG, S_FILE_FLAG ;source filename entered
1023 call chk_s_reserved_name ;is it a reserved name?
1024; $ELSE
1025 JMP SHORT $$EN90
1026$$IF90:
1027 MOV DX, MSG_INVALID_PATH ;AC000;GET THE MESSAGE ID
1028 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error
1029; $ENDIF
1030$$EN90:
1031; $ENDIF
1032$$EN88:
1033; $ENDIF
1034$$EN86:
1035; $ENDIF
1036$$EN84:
1037 TEST PARM_FLAG, INIT_ERROR_FLAG
1038; $IF Z,LONG ;no error so far,
1039 JZ $$XL2
1040 JMP $$IF96
1041$$XL2:
1042 TEST SYS_FLAG, ONE_DISK_COPY_FLAG ;if one disk copy
1043; $IF NZ ;then saved source default directory
1044 JZ $$IF97
1045 LEA DX, SAV_S_DRV ;is the same as target current dir
1046 MOV AH, Chdir ;=3Bh
1047 INT 21h ;so restore target default dir.
1048; $ENDIF
1049$$IF97:
1050 MOV DL, T_DRV_NUMBER
1051 LEA SI, SAV_T_CURDIR
1052 CALL GET_CUR_DIR ;save current target directory
1053 OR SYS_FLAG, DEFAULT_T_DIR_FLAG ;indicates target dir saved
1054 TEST PARM_FLAG, SECOND_PARM_FLAG ;second parm has been entered?
1055; $IF Z ;second parm not entered
1056 JNZ $$IF99
1057 LEA SI, T_PATH
1058 CALL GET_CUR_DIR ;make the current target dir as T_PATH
1059; $ELSE ;then deals with the second parm
1060 JMP SHORT $$EN99
1061$$IF99:
1062
1063 LEA DX, T_INPUT_PARM ;try to chdir according to T_INPUT
1064 MOV AH, Chdir
1065 INT 21h ;= 3Bh
1066; $IF C ;FAILURE?
1067 JNC $$IF101
1068 CALL PARSE_SECOND_PARM
1069; $ENDIF
1070$$IF101:
1071
1072 TEST PARM_FLAG, INIT_ERROR_FLAG ;no error so far?
1073; $IF Z ;no error
1074 JNZ $$IF103
1075 MOV DL, T_DRV_NUMBER
1076 LEA SI, T_PATH
1077 CALL GET_CUR_DIR ;save target starting dir
1078 CMP TEMP_T_FILENAME, 0 ;any non_global target file name entered?
1079; $IF NE ;yes
1080 JE $$IF104
1081 MOV CX, 13 ;maximum 13 char.
1082 LEA SI, TEMP_T_FILENAME
1083 LEA DI, T_FILENAME ;then move it to T_FILENAME while convert it to capital letter.
1084 CALL MOV_STRING ;AC000; SI => DI
1085; $ENDIF
1086$$IF104:
1087; $ENDIF ;end - no error so far
1088$$IF103:
1089; $ENDIF ;end - second parm not entered
1090$$EN99:
1091; $ENDIF
1092$$IF96:
1093
1094 TEST PARM_FLAG, INIT_ERROR_FLAG
1095; $IF Z ;no error
1096 JNZ $$IF109
1097 CALL CHK_CYCLIC_COPY ;check source, target parms
1098 TEST PARM_FLAG, INIT_ERROR_FLAG ;cyclic copy?
1099; $IF Z,AND ;no
1100 JNZ $$IF110
1101 TEST SYS_FLAG, ONE_DISK_COPY_FLAG ;if one disk drv letter copy
1102; $IF NZ ;then set the starting dir
1103 JZ $$IF110
1104 LEA DX, S_DRV_PATH ;to that of source.
1105 MOV AH, Chdir ; = 3Bh
1106 INT 21H ;should succeed since alreay tested.
1107; $ENDIF
1108$$IF110:
1109; $ENDIF
1110$$IF109:
1111
1112 RET
1113CHK_SET_PARMS ENDP
1114;
1115PARSE_SECOND_PARM PROC NEAR
1116;called after the initial chdir to T_INPUT_PARM failed. Remember the second parm should
1117;exist when you call this routine.
1118;INPUT: DS, ES - data seg
1119;OUTPUT:if error, init_error_flag will be set.
1120;
1121 LEA SI, T_INPUT_PARM
1122 CALL CHK_HEAD_PARM ;check the head part of parm. SI will points
1123 ;to the next chr after the header.
1124 TEST PARM_FLAG, INIT_ERROR_FLAG
1125 JNZ PSP_EXIT ;YES, ERROR.
1126 CALL NEXT_PATH_DELIM ;Let SI points to the next path delim "\" or 0
1127 LEA DX, T_INPUT_PARM
1128 CALL PARSING_T_PATH ;chdir for every directory starting from the
1129 ;first. If it fails, then create a directory
1130 ;and chdir to it.
1131PSP_EXIT:
1132 RET
1133PARSE_SECOND_PARM ENDP
1134;
1135NEXT_PATH_DELIM PROC NEAR
1136;starting from SI, check every chr until it is '\' or 0 or ':'.
1137;if the starting chr is '\' or 0 or ':', then SI won't change.
1138;the caller should be sure that it is an ASCIIZ string.
1139;INPUT: DS, ES - data seg
1140; SI - starting point
1141;OUTPUT:
1142; SI - next path delimeter
1143
1144 CLD
1145 PUSH DI
1146 PUSH SI
1147 POP DI ;NOW DI POINTS TO THE STARTING CHR
1148NPD_LOOP:
1149; $DO ;AN010;
1150$$DO113:
1151 CLC ;AN010;INITIALIZE TO NOT DBCS
1152 MOV AL,BYTE PTR [DI] ;AN010;GET THE 1st CHAR TO TEST
1153 CALL CHK_DBCS ;AN010;SEE IF WE ARE IN DBCS
1154; $LEAVE NC ;AN010;THIS IS NOT DBCS
1155 JNC $$EN113
1156 INC DI ;AN010;GO TO THE NEXT CHAR TO CHECK
1157 INC DI ;AN010;DITO
1158; $ENDDO ;AN010;
1159 JMP SHORT $$DO113
1160$$EN113:
1161 MOV AL, 0
1162 SCASB ;0 - ES:[DI], DI=DI+1
1163 JZ NPD_FOUND
1164 DEC DI ;check it again if it is '\'
1165 MOV AL, '\'
1166 SCASB
1167 JZ NPD_FOUND
1168 DEC DI
1169 MOV AL, ':' ;is it a filename terminator not filter before?
1170 SCASB
1171 JZ NPD_FOUND
1172 JMP SHORT NPD_LOOP
1173NPD_FOUND:
1174 DEC DI ;adjust DI to the chr found
1175 PUSH DI
1176 POP SI ;now SI points to the chr
1177 POP DI ;restore DI
1178 RET
1179NEXT_PATH_DELIM ENDP
1180;
1181
1182CHK_HEAD_PARM PROC NEAR
1183;check the starting header part of parameter pointed by SI to eliminate
1184;error such as A:\\..., A:\.., \\, \.. etc.
1185;This routine will change the current target directory to the root
1186;when "d:\" or "\" has been found.
1187;The parameter string should be ASCIIZ and should exist.
1188;INPUT: DS, ES - DATA SEG
1189; SI - POINTS TO THE PARAMETER
1190;OUTPUT:SI POINTS TO THE NEXT VALID PATH
1191; DX WILL POINTS TO THE ERROR MESSAGE
1192
1193 CALL CHK_DRV_LETTER ;si points to the next chr after drv letter, if found.
1194 CMP BYTE PTR [SI], 0 ;"A:0" case
1195; $IF E
1196 JNE $$IF116
1197 MOV BYTE PTR [SI], '.'
1198 INC SI
1199 MOV BYTE PTR [SI], 0 ;make it "A:.0"
1200; $ELSE
1201 JMP SHORT $$EN116
1202$$IF116:
1203 CMP BYTE PTR [SI], '\'
1204; $IF E ;A:\--- or \--- cases
1205 JNE $$IF118
1206 INC SI
1207 CLC ;AN010;INITIALIZE TO NOT DBCS
1208 MOV AL,DS:BYTE PTR [SI] ;AN010;GET THE 1st CHAR TO TEST
1209 CALL CHK_DBCS ;AN010;SEE IF WE ARE IN DBCS
1210; $IF NC ;AN010;THIS IS NOT DBCS
1211 JC $$IF119
1212 CMP BYTE PTR [SI], '\'
1213; $IF E ;A:\\--- or \\--- cases ; ERROR
1214 JNE $$IF120
1215 MOV DX, MSG_INVALID_PATH ;AC000;GET THE MESSAGE ID
1216 OR PARM_FLAG, INIT_ERROR_FLAG
1217; $ELSE
1218 JMP SHORT $$EN120
1219$$IF120:
1220 CMP BYTE PTR [SI], '.'
1221; $IF E ;A:\.--- or \.--- cases
1222 JNE $$IF122
1223 INC SI
1224 MOV AL,DS:BYTE PTR [SI] ;AN010;GET 1st CHAR
1225 ; TO TEST
1226 CALL CHK_DBCS ;AN010;SEE IF WE ARE IN
1227 ; DBCS
1228; $IF NC ;AN010;THIS IS NOT DBCS
1229 JC $$IF123
1230 CMP BYTE PTR [SI], '.'
1231; $IF E,OR
1232 JE $$LL124
1233 CMP BYTE PTR [SI], '\'
1234; $IF NE ;if not A:\.\--- or \.\--- cases
1235 JE $$IF124
1236$$LL124:
1237 MOV DX, MSG_INVALID_PATH ;AC000;MSG ID
1238 OR PARM_FLAG, INIT_ERROR_FLAG
1239; $ENDIF
1240$$IF124:
1241; $ENDIF ;AN010;END OF DBCS TEST
1242$$IF123:
1243 CLC ;AN010;
1244; $ENDIF
1245$$IF122:
1246; $ENDIF
1247$$EN120:
1248 LEA DX, T_DRV
1249 MOV AH, Chdir
1250 INT 21h ;"Chdir to root" is no problem.
1251; $ENDIF ;AN010;DBCS TEST END
1252$$IF119:
1253 CLC ;AN010;
1254; $ENDIF
1255$$IF118:
1256; $ENDIF
1257$$EN116:
1258 RET
1259CHK_HEAD_PARM ENDP
1260;
1261PARSING_T_PATH PROC NEAR
1262;chdir to every path element from the first. If fails, create the directory and
1263;try to chdir again. T_MKDIR_LVL will increase when new starting directory is created
1264;INPUT: DX - OFFSET OF T_INPUT_PARM
1265; SI - points to '\' or 0, or ':'
1266;OUTPUT: directories are created if necessary.
1267; DX points to the last path entry
1268; if fails to create a directory, then INIT_ERROR_FLAG set and
1269; DX points to MSG_NOT_CREATE_DIR msg.
1270
1271 PUSH DX ;save DX
1272 MOV DL, T_DRV_NUMBER
1273 DEC DL
1274 CALL SET_DEFAULT_DRV ;set target drive as a default
1275 POP DX ;restore DX
1276PTP_NEXT:
1277 CMP BYTE PTR [SI], 0 ;end of string? the last path element?
1278 JE PTP_LAST
1279 CMP BYTE PTR [SI], ':' ;filename terminator not checked before?
1280 JNE PTP_CHDIR ;else it is '\'.
1281 MOV BYTE PTR [SI], 0 ;change ':' to 0 for termination.
1282PTP_LAST:
1283 CALL LAST_T_PATH
1284 JMP PTP_EXIT
1285PTP_CHDIR:
1286 MOV BYTE PTR [SI], 0 ;replace '\' with 0
1287 MOV AH, Chdir ;=38h
1288 INT 21h
1289 JC PTP_MKDIR
1290 MOV BYTE PTR [SI], '\' ;restore '\'
1291 INC SI ;SI points to next to old '\'
1292 MOV DX, SI ;DX points to next path entry
1293 CALL NEXT_PATH_DELIM
1294 JMP PTP_NEXT ;handles next path element
1295PTP_MKDIR:
1296 MOV AH, Mkdir ;=39h
1297 INT 21h
1298 JC PTP_ERROR ;cannot make directory
1299 INC T_MKDIR_LVL ;# of MKDIR for the starting directory.
1300 JMP PTP_CHDIR ;try again to chdir
1301PTP_ERROR:
1302 MOV DX, MSG_NOT_CREATE_DIR ;AC000;GET THE MESSAGE ID
1303 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error
1304PTP_EXIT:
1305 RET
1306
1307PARSING_T_PATH ENDP
1308;
1309LAST_T_PATH PROC NEAR
1310;called when the second parm reached last. *** this routine is the same as the old routine ***
1311;and the initial try to chdir to the given T_INPUT_PARM has been failed.
1312;INPUT: ES, DS - data seg
1313; DX - points to the last path entry
1314;OUTPUT:target starting directory.
1315
1316 MOV AH, Chdir ;try to chdir to the last path entry
1317 INT 21h
1318; $IF C,LONG ;if fail.
1319 JC $$XL3
1320 JMP $$IF132
1321$$XL3:
1322
1323 LEA BX, T_INPUT_PARM
1324 LEA DX, TEMP_T_FILENAME ;take the last path element into TEMP_T_FILENAME
1325 CALL TAKE_PATH_TAIL
1326 CMP TEMP_T_FILENAME, 0 ;any filename candidate entered?
1327; $IF NE,LONG ;yes. let's check it has any global chr.
1328 JNE $$XL4
1329 JMP $$IF133
1330$$XL4:
1331 PUSH ES
1332 MOV AH, 29h
1333 LEA SI, TEMP_T_FILENAME
1334 MOV ES, PSP_SEG ;ES - psp seg
1335 MOV DI, PSPFCB2_DRV ;use this area for this test purposes
1336 MOV AL, 0 ;control bit
1337 INT 21h
1338 POP ES
1339 CMP AL, 0 ;no global filename entered?
1340; $IF E ;yes, no globals
1341 JNE $$IF134
1342 CALL PROMPT_CREATE_DIR ;then ask the user, it is a filename or subdir name?
1343 MOV DX,USER_INPUT ;AN000;SET UP FOR COMPAIR
1344 CMP DX, alpha_dir ;directory?
1345; $IF E ;yes, a subdir name.
1346 JNE $$IF135
1347 LEA DX, TEMP_T_FILENAME
1348 MOV AH, Mkdir ;=39h
1349 INT 21h ;create a new subdir
1350; $IF NC
1351 JC $$IF136
1352 INC T_MKDIR_LVL ;one more directory has been made.
1353 MOV AH, Chdir
1354 INT 21h ;Chdir to a new dir. This time it should be a success.
1355 MOV TEMP_T_FILENAME, 0 ;mark temp_t_filename that it is empty
1356; $ELSE ;ERROR IN CREATING DIRECTORY
1357 JMP SHORT $$EN136
1358$$IF136:
1359 MOV DX, MSG_NOT_CREATE_DIR ;AC000;GET THE MESSAGE ID
1360 OR PARM_FLAG, INIT_ERROR_FLAG
1361; $ENDIF
1362$$EN136:
1363; $ELSE ;USER ANSWERED IT A FILENAME
1364 JMP SHORT $$EN135
1365$$IF135:
1366 OR PARM1_FLAG, T_FILE_FLAG ;set target file entered.
1367; $ENDIF ;use TEMP_T_FILENAME as a filename
1368$$EN135:
1369; $ELSE ;GLOBALS IN THE FILENAME
1370 JMP SHORT $$EN134
1371$$IF134:
1372 MOV TEMP_T_FILENAME, 0 ;mark it to 0 since we don;t need this.
1373 CALL MAKE_TEMPLATE ;make a template of the target filename
1374 OR PARM1_FLAG, T_FILE_FLAG ;set target file entered flag
1375; $ENDIF ;GLOBAL TEST
1376$$EN134:
1377; $ENDIF ;NO, FILENAME NOT ENTERED. TEMP_T_FILENAME = 0
1378$$IF133:
1379; $ENDIF ;CHDIR FAIL
1380$$IF132:
1381 RET
1382LAST_T_PATH ENDP
1383;
1384;
1385CHK_S_RESERVED_NAME PROC NEAR
1386;check the source filename entered, and if it does not have any global chr,
1387;then check it whether it is reserved filename or not.
1388;input: es,ds - data seg
1389
1390 mov ax, 3d00h ;let's try to open it
1391 lea dx, s_drv_1 ;'A:S_FILE'
1392 int 21h
1393 jc csrn_exit ;open failure? jmp to exit
1394 mov bx, ax ;else ax has file handle
1395 mov ax, 4400h ;get device info.
1396 int 21h ;ioctl fun call
1397 test dx, 80h ;ISDEV ?
1398 jz csrn_close ;no, block device. close handle and exit
1399 PUSH AX ;AN000;
1400 MOV AX, msg_res_s_name ;AC000;reserved file name as a source"
1401 MOV MSG_NUM,AX ;AN000;NEED MESSAGE ID FOR PRINT
1402 MOV SUBST_COUNT,NO_SUBST ;AN000;NO SUBSTITUTION TEXT
1403 MOV INPUT_FLAG,NO_INPUT ;AN000;NO INPUT = 0
1404 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
1405 CALL PRINT_STDERR ;AN000;print error. AX points to msg ID
1406 POP AX ;AN000;
1407 mov errorlevel, 4 ;abnormal termination
1408 or parm_flag, init_error_flag ;set init_error_flag
1409 jmp main_exit
1410csrn_close:
1411 mov ah, 3eh ;close filehandle in bx
1412 int 21h
1413csrn_exit:
1414 ret
1415CHK_S_RESERVED_NAME ENDP
1416;
1417PROMPT_CREATE_DIR PROC NEAR
1418;DS, ES - data seg
1419 PUSH AX ;AN000;
1420 mov cx, 13
1421 lea si, temp_t_filename
1422 lea di, filename_for_prompt
1423 call mov_STRING ;AC000;
1424
1425;CALL GET MESSAGE TO DETERMINE WHAT THIS COUNTRY INPUT FOR 'F' OR 'D' IS.
1426
1427 PUSH DS ;AN000;
1428 ASSUME DS:NOTHING ;AN000;TELL THE ASSEMBLER
1429 MOV AX,MSG_F_D ;AN000;MESSAGE NUMBER = 29 = 'F D '
1430 MOV DH,UTILITY_MSG_CLASS ;AN000;MESSAGE DEFINED FOR XCPYINIT
1431 CALL SYSGETMSG ;AN000;GET THE MESSAGE
1432 LODSW ;AN000;'F'PART OF MSG (DS:SI => AX)
1433 CMP AH,SPACE ;AN000;NOT 'SPACE' THEN IT IS DBCS !
1434; $IF E ;AN000;IGNORE THE NEXT WORD
1435 JNE $$IF145
1436 MOV AH,NUL ;AN000;THE END OF THE STRING
1437; $ENDIF ;AN000;NOW GET TRANSLATION OF 'D'
1438$$IF145:
1439 MOV ES:ALPHA_FILE,AX ;AN000;TRANSLATED CHAR FOR 'F' TO BUFF
1440 LODSW ;AN000;'D'PART OF MSG (DS:SI => AX)
1441 CMP AH,SPACE ;AN000;NOT 'SPACE' THEN IT IS DBCS !
1442; $IF E ;AN000;IGNORE THE NEXT WORD
1443 JNE $$IF147
1444 MOV AH,NUL ;AN000;REMOVE SPACE CHARACTER
1445; $ENDIF ;AN000;NOW GET TRANSLATION OF 'D'
1446$$IF147:
1447 MOV ES:ALPHA_DIR,AX ;AN000;TRANSLATED CHAR FOR 'D' TO BUFF
1448 POP DS ;AN000;RESTORE AFTER CALL TO MSG HANDLR
1449 ASSUME DS:DGROUP ;AN000;TELL THE ASSEMBLER
1450 ;remember this may be DBCS
1451PCD_AGAIN:
1452; Set message substitution list
1453 LEA SI,SUBLIST1 ;AN000; get addressability to sublist
1454 LEA DX,FILENAME_FOR_PROMPT ;AN000; offset to file name
1455 MOV [SI].DATA_OFF,DX ;AN000; save data offset
1456 MOV [SI].DATA_SEG,DS ;AN000; save data segment
1457 MOV [SI].MSG_ID,1 ;AN000; message ID
1458 MOV [SI].FLAGS,010H ;AN000; ASCIIZ string, left align
1459 MOV [SI].MAX_WIDTH,0 ;AN000; MAXIMUM FIELD WITH
1460 MOV [SI].MIN_WIDTH,0 ;AN000; MINIMUM FIELD WITH
1461
1462 MOV AX,MSG_CREATE_DIR ;AN000;ID OF MESSAGE TO BE DISPLAYED
1463 MOV MSG_NUM,AX ;AN000;SET THE MESSAGE NUMBER
1464 MOV SUBST_COUNT,PARM_SUBST_ONE ;AN000;PARM SUBSTITUTION COUNT=1
1465 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
1466 MOV INPUT_FLAG,KEYBOARD_INPUT ;AN000;KEYBOARD INPUT EXPECTED FUNCTION
1467 CALL PRINT_STDOUT ;show prompt and get user input
1468
1469 MOV USER_INPUT,AX ;AN000;RESPONSE BUFF FOR CAPITALIZATION
1470
1471 MOV AX,MSG_CR_LF_STR ;AN000; JUST CR,LF
1472 MOV MSG_NUM,AX ;AN000; set message number
1473 MOV SUBST_COUNT,NO_SUBST ;AN000;NO PARAMETER SUBSTITUTION
1474 MOV INPUT_FLAG,NO_INPUT ;AN000; NO INPUT
1475 CALL PRINT_STDOUT ;AN000; Display message
1476
1477 MOV AX,UPPER_CASE_STRING ;AN000;AX = 6521H GET EXT CTRY INFO
1478 LEA DX,USER_INPUT ;AN000;RESPONSE BUFF FOR CAPITALIZATION
1479 MOV CX,2 ;AN000;TWO CHARACTERS, ONE WORD
1480 INT 21H ;AN000;ISSUE INT TO CAP STRING (DBCS?)
1481 MOV AX,USER_INPUT ;AN000;SO I CAN DO THE COMPARE
1482 CMP AX,ALPHA_FILE ;AN000;KEYBOARD INPUT AX = 'F' ?
1483 JE PCD_EXIT
1484 CMP AX,ALPHA_DIR ;AN000;KEYBOARD INPUT AX = 'D' ?
1485 JE PCD_EXIT
1486 JMP SHORT PCD_AGAIN
1487PCD_EXIT:
1488
1489 POP AX ;AN000;
1490 RET
1491PROMPT_CREATE_DIR ENDP
1492;
1493TAKE_PATH_TAIL PROC NEAR
1494;check the tail of the source input parm.
1495;Call LAST_DIR_OUT
1496;If carry set
1497; then check the drive letter
1498; if entered, then save the rest of the string after drv: into
1499; a tempory filename holder, and put "." after the drive letter
1500; (For ex, if the input had been 'A:name1',0 then no change after
1501; LAST_DIR_OUT. This has to be changed to 'A:.',0 and name1.)
1502; else save the last dir into a filename, and
1503; check the result path
1504; if it is a drive only, then put "\" ( For ex, if the input
1505; had been 'A:\name1',0 then after LAST_DIR_OUT, it will be changed
1506; to 'A:',0 and 'name1',0. In this case, we have to change the
1507; path to A:\)
1508; else OK.
1509;INPUT: DS - data seg
1510; ES - data seg
1511; BX - offset value of S_INPUT_PARM or T_INPUT_PARM
1512; DX - offset value of TEMP_S_FILENAME or TEMP_T_FILENAME
1513
1514
1515 MOV DI, BX ;offset of S(T)_INPUT_PARM
1516 CALL LAST_DIR_OUT
1517; $IF C ;Not found a "\"
1518 JNC $$IF149
1519 MOV SI, DI ;set si = di
1520 CALL CHK_DRV_LETTER ;if drv letter:, then SI will
1521 ;point to next chr. Otherwise no change
1522 cmp byte ptr [si], 0 ;only drv letter has entered. No filename
1523; $IF NE ;filename entered
1524 JE $$IF150
1525 push si ;save si
1526 MOV CX, 13 ;max # of filename in ASCIIZ
1527 MOV DI, DX
1528 REP MOVSB ;save it to temporay name holder
1529 pop si ;restore si
1530; $ENDIF
1531$$IF150:
1532 mov byte ptr [si], A_dot ;to be used for Chdir fun call
1533 mov byte ptr [si+1], 0 ;make it ASCIIZ
1534; $ELSE ;at least found a "\"
1535 JMP SHORT $$EN149
1536$$IF149:
1537 mov cx, 13 ;let's save tail into filename holder first
1538 mov si, ax ;AX is an offset value of the tail
1539 mov di, DX ;TEMP_FILENAME
1540 rep movsb
1541 mov si, BX ;return to the Revised input
1542 CALL CHK_DRV_LETTER ;it starts with drv letter?
1543 cmp byte ptr [si], 0 ;si points to the end of string?
1544; $IF E
1545 JNE $$IF153
1546 MOV byte ptr [SI], '\' ;then add '\' in the Revised S_INPUT_PARM
1547 MOV byte ptr [SI+1], 0
1548; $ENDIF
1549$$IF153:
1550; $ENDIF
1551$$EN149:
1552 RET
1553
1554TAKE_PATH_TAIL ENDP
1555;
1556CHK_CYCLIC_COPY PROC NEAR
1557;With the one_disk_copy case, if the starting source path is a member of
1558;parent directory of the startind target path, then infinite copy cycle
1559;can occur. This routine prevents that situation.
1560;ES: data seg
1561;DS: data seg
1562
1563 PUSH DS
1564 POP ES ;set ES to DS (ES = DS)
1565 CALL TRANS_NAMES ;AN016;CHK ASSIGN, JOIN & SUBST CONDITN
1566 TEST SYS_FLAG, ONE_DISK_COPY_FLAG ;source, target drv let same
1567; $IF NZ ;if they are, then check below facts
1568 JZ $$IF156
1569 MOV DI, OFFSET DGROUP:T_TRANS_PATH ;AC025;
1570 MOV AL, 0
1571 CALL STRING_LENGTH
1572 MOV DX, CX ;save the length of S_PATH
1573 MOV DI, OFFSET DGROUP:S_TRANS_PATH ;AC025;
1574 CALL STRING_LENGTH
1575 CMP DX,CX ;compare the length
1576; $IF AE ;if target length >= source length
1577 JNAE $$IF157
1578 MOV SI, OFFSET DGROUP:S_TRANS_PATH ;AC025;
1579 MOV DI, OFFSET DGROUP:T_TRANS_PATH ;AC025;
1580 DEC CX ;get the actual length of chr's
1581 DEC DX
1582 CLD
1583; $SEARCH ;current CX = source length
1584$$DO158:
1585 CMP CX, 0
1586; $EXITIF E ;exit if cx = 0
1587 JNE $$IF158
1588 CMP DX, 0 ;target length = 0 too?
1589; $IF E ;yes, source = target
1590 JNE $$IF160
1591 TEST OPTION_FLAG, SLASH_S ; tree copy?
1592; $IF NZ,OR ;yes
1593 JNZ $$LL161
1594 TEST OPTION_FLAG, SLASH_E
1595; $IF NZ
1596 JZ $$IF161
1597$$LL161:
1598 MOV DX, MSG_CYCLIC_COPY ;AC000;GET THE MESSAGE ID
1599 OR PARM_FLAG, INIT_ERROR_FLAG ;critical error
1600; $ELSE ;same length, but not a tree copy.
1601 JMP SHORT $$EN161
1602$$IF161:
1603 OR COPY_STATUS, MAYBE_ITSELF_FLAG ;possibly, copy onto itself.
1604; $ENDIF ;cannot fully determine this time until file creation time
1605$$EN161:
1606; $ELSE ;target > source
1607 JMP SHORT $$EN160
1608$$IF160:
1609 TEST OPTION_FLAG, SLASH_S ;tree copy?
1610; $IF NZ,OR
1611 JNZ $$LL165
1612 TEST OPTION_FLAG, SLASH_E
1613; $IF NZ
1614 JZ $$IF165
1615$$LL165:
1616 CMP BYTE PTR [DI], '\' ;source = d:\abc, target = d:\abc\def case
1617; $IF E,OR
1618 JE $$LL166
1619 CMP BYTE PTR [DI-1], '\' ;source = d:\, target=d:\abc case
1620; $IF E
1621 JNE $$IF166
1622$$LL166:
1623 MOV DX, MSG_CYCLIC_COPY ;AC000;GET THE MESSAGE ID
1624 OR PARM_FLAG, INIT_ERROR_FLAG ; critical error
1625; $ENDIF
1626$$IF166:
1627; $ENDIF
1628$$IF165:
1629; $ENDIF
1630$$EN160:
1631; $ORELSE
1632 JMP SHORT $$SR158
1633$$IF158:
1634 LODSB ;[SI] => AL, SI = SI + 1
1635 SCASB ;AL vs. [DI], DI = DI + 1
1636; $LEAVE NE ;leave if not same
1637 JNE $$EN158
1638 DEC CX
1639 DEC DX ;decrease target length, too
1640; $ENDLOOP
1641 JMP SHORT $$DO158
1642$$EN158:
1643; $ENDSRCH
1644$$SR158:
1645; $ENDIF
1646$$IF157:
1647; $ENDIF
1648$$IF156:
1649 RET
1650
1651CHK_CYCLIC_COPY ENDP
1652;
1653TRANS_NAMES PROC NEAR
1654;TRANSLATE THE INPUT TARGET AND SOURCE PATH TO DETERMINE
1655;IF ASSIGN, JOIN OR SUBSD WAS USET TO MODIFY HIDE THE TRUE
1656;PATH. THIS INFO. WILL BE USED TO DETERMINE CYCLIC COPY.
1657;INPUT: T_DRV_PATH, S_DRV_PATH
1658
1659 PUSH SI ;AN016;SI WILL BE DESTROYED
1660 PUSH DI ;AN016;DI WILL BE DESTROYED
1661
1662 MOV SI,OFFSET DGROUP:T_DRV_PATH ;AN016;DO NAME TRANSLATE OF TAR
1663 MOV DI,OFFSET DGROUP:T_TRANS_PATH ;AN025;SAVE FOR COMPARE
1664 MOV AH,60h ;AN016;NAMETRANSLATE
1665 INT 21h ;AN016;EXECUTE
1666
1667 MOV SI,OFFSET DGROUP:S_DRV_PATH ;AN016;DO NAME TRANSLATE OF SRC
1668 MOV DI,OFFSET DGROUP:S_TRANS_PATH ;AN025;SAVE FOR COMPARE
1669 MOV AH,60h ;AN016;NAMETRANSLATE
1670 INT 21h ;AN016;EXECUTE
1671
1672;NOW COMPARE THE TRANSLATED NAMES
1673
1674 MOV SI,OFFSET DGROUP:T_TRANS_PATH ;AN025;GET THE TAR FOR COMPARE
1675 MOV DI,OFFSET DGROUP:S_TRANS_PATH ;AN025;GET THE SRC FOR COMPARE
1676 CALL STR_COMP ;AN016;DO THE COMPARE
1677; $IF Z ;AN016;STRING DID COMPARE
1678 JNZ $$IF176
1679 OR SYS_FLAG, ONE_DISK_COPY_FLAG ;AN016;source, target drv let same
1680; $ENDIF ;AN016;
1681$$IF176:
1682
1683 POP DI ;AN016;restore DI
1684 POP SI ;AN016;restore SI
1685 RET
1686TRANS_NAMES ENDP
1687;
1688STR_COMP PROC NEAR
1689;COMPARE ASCIIZ DS:SI WITH ES:DI
1690;DI,SI ARE DESTROYED
1691
1692STRCOMP:
1693 CMPSB ;AN016;ONE BYTE AT A TIME
1694; $IF NZ ;AN016;DID NOT COMPARE
1695 JZ $$IF178
1696 RET ;AN016;NZ = DIFFERENCE
1697; $ENDIF ;AN016;
1698$$IF178:
1699 CMP BYTE PTR [SI-1],NUL ;AN016;CHK FOR END OF THE STRING
1700; $IF Z ;ANO16;IT IS E O S
1701 JNZ $$IF180
1702 RET ;AN016;IT COMPARED
1703; $ENDIF ;AN016;
1704$$IF180:
1705 JMP SHORT STRCOMP ;AN016;GO AGAIN
1706STR_COMP ENDP
1707
1708MAKE_TEMPLATE PROC NEAR
1709;copy the formatted filename into the T_TEMPLATE which will be
1710;used to name a new filename.
1711;INPUT: PSP FCB 6ch for filename which have global chr.
1712;
1713 PUSH DS ;ES = DS = DATA SEG
1714
1715 MOV DS, PSP_SEG ;DS = PSP_SEG
1716
1717 MOV SI, PSPFCB2_DRV
1718 INC SI
1719 LEA DI, T_TEMPLATE
1720 MOV CX, 11
1721 REP MOVSB ;filename => t_template
1722
1723 POP DS ;restore DS
1724 RET
1725MAKE_TEMPLATE ENDP
1726
1727GET_DRIVES PROC NEAR
1728;get source and target phisical drive letter from parser area.
1729;set ONE_DISK_COPY_FLAG, if the user XCOPY using the same drive letter.
1730
1731 MOV AL, SO_DRIVE ;AN000;source drive letter
1732 CMP AL,SPACE ;AN000;IS DRIVE LETTER BLANK?
1733; $IF E ;AN000;YES, GET THE DEFAULT
1734 JNE $$IF182
1735 MOV AL, SAV_DEFAULT_DRV ;(1=A, 2=B,...)
1736; $ELSE ;AN000;NO, CHANGE FROM CHAR TO #
1737 JMP SHORT $$EN182
1738$$IF182:
1739 SUB AL,BASE_OF_ALPHA_DRV ;AN000;NEED THE DRV # HERE
1740; $ENDIF
1741$$EN182:
1742 MOV S_DRV_NUMBER, AL ;SAVE DRV #
1743 ADD AL, BASE_OF_ALPHA_DRV
1744 MOV S_DRV, AL ;save source drive letter
1745 MOV S_DRV_1, AL
1746 MOV S_ARC_DRV, AL
1747 MOV SAV_S_DRV, AL
1748
1749 MOV AL, TAR_DRIVE ;AN000;target drive letter
1750 CMP AL,SPACE ;AN000;IS DRIVE LETTER BLANK?
1751; $IF E ;AN000;YES, GET THE DEFAULT
1752 JNE $$IF185
1753 MOV AL, SAV_DEFAULT_DRV ;AN000;(1=A, 2=B,...)
1754; $ELSE ;AN000;NO, CHANGE FROM CHAR TO #
1755 JMP SHORT $$EN185
1756$$IF185:
1757 SUB AL,BASE_OF_ALPHA_DRV ;AN000;NEED THE DRV # HERE
1758; $ENDIF
1759$$EN185:
1760 MOV T_DRV_NUMBER, AL ;save target drv #
1761
1762 CMP S_DRV_NUMBER, AL ;s_drv_number = t_drv_number?
1763; $IF E
1764 JNE $$IF188
1765 OR SYS_FLAG, ONE_DISK_COPY_FLAG ;same logical drv copy
1766; $ENDIF
1767$$IF188:
1768
1769 ADD AL, BASE_OF_ALPHA_DRV ;make target drv # to drive letter
1770 MOV T_DRV, AL ;target drive letter
1771 MOV T_DRV_1, AL
1772 MOV T_DRV_2, AL
1773 MOV SAV_T_DRV, AL
1774 RET
1775GET_DRIVES ENDP
1776;
1777;
1778GET_CUR_DRV PROC NEAR
1779;get the current default drive number (0 = A, 1 = B ..),
1780;change it to BIOS drive number and save it.
1781 MOV AH, Current_Disk ; = 19h
1782 INT 21h
1783 INC AL ;(1 = A, 2 = B ..)
1784 MOV SAV_DEFAULT_DRV, AL ;save it
1785 RET
1786GET_CUR_DRV ENDP
1787;
1788GET_CUR_DIR PROC NEAR
1789;get current directory and save it
1790;input: DL - drive # (0 = default, 1 = A etc)
1791; DS:SI - pointer to 64 byte user memory
1792
1793 MOV AH, Get_Current_Directory
1794 INT 21H
1795 RET
1796GET_CUR_DIR ENDP
1797;
1798TOP_OF_MEM PROC NEAR
1799;set Top_of_memory
1800
1801 PUSH ES
1802 MOV BX, PSP_SEG
1803 MOV ES, BX
1804 MOV AX, ES:2 ;PSP top of memory location
1805 SUB AX, 140H ;subtract dos transient area (5k)
1806 MOV TOP_OF_MEMORY, AX ;save it for buffer top
1807 POP ES
1808 RET
1809TOP_OF_MEM ENDP
1810
1811INIT_BUFFER PROC NEAR
1812;initialize buffer information
1813;set buffer_base, max_buffer_size
1814; call set_block ;SET BLOCK FOR BUFFR (for new 3.2 linker)
1815 MOV AX, OFFSET INIT
1816 PUSH CS ;cs segment is the highest segment in this program
1817 POP DX
1818 MOV BUFFER_PTR, DX
1819 CALL SET_BUFFER_PTR
1820 MOV AX, BUFFER_PTR
1821 MOV BUFFER_BASE, AX ;set buffer_base
1822 MOV AX, BUFFER_LEFT
1823 CMP AX, 140h ;BUFFER_LEFT < 5K which is the minimum size this program supports?
1824 JAE IB_CONT
1825 PUSH AX ;AN000;
1826 MOV AX, MSG_INSUF_MEMORY ;AC000;GET THE MESSAGE ID
1827 MOV MSG_NUM,AX ;AN000;NEED MESSAGE ID FOR PRINT
1828 MOV SUBST_COUNT,NO_SUBST ;AN000;NO SUBSTITUTION TEXT
1829 MOV INPUT_FLAG,NO_INPUT ;AN000;NO INPUT = 0
1830 MOV MSG_CLASS,UTILITY_MSG_CLASS ;AN000;MESSAGE CLASS = -1
1831 CALL PRINT_STDERR ;AN000;print error. AX points to msg ID
1832 POP AX ;AN000;
1833 MOV ERRORLEVEL, 4 ;abnormal termination
1834 JMP MAIN_EXIT_A ;terminate this program
1835IB_CONT:
1836 MOV MAX_BUFFER_SIZE, AX ;set max buffer size in para
1837 CMP AX, 0FFFh ;max_buffer_size > 64 K in para ?
1838; $IF B
1839 JNB $$IF190
1840 MOV CX, 16
1841 MUL CX ;AX = AX * 16 (DX part will be 0)
1842 SUB AX, 544 ;AN000;subtract header size
1843 MOV MAX_CX, AX ;this will be max_cx
1844; $ELSE
1845 JMP SHORT $$EN190
1846$$IF190:
1847 MOV MAX_CX, 0FFD0h ;else max_cx = fff0 - 32 bytes
1848 ;which is the max # this program can support.
1849; $ENDIF ;(min # this program support for buffer is 5 k
1850$$EN190:
1851 ; which has been decided by BIG_FILE )
1852 RET
1853INIT_BUFFER ENDP
1854;
1855HOOK_CTRL_BREAK PROC NEAR
1856;
1857 PUSH DS ;save DS
1858 PUSH CS
1859 POP DS ;ds = cs
1860 MOV AX, 2523h
1861 MOV DX, OFFSET CTRL_BREAK_EXIT
1862 INT 21H
1863 POP DS ;restore ds
1864 RET
1865HOOK_CTRL_BREAK ENDP
1866;
1867SAV_HOOK_INT24 PROC NEAR
1868;sav the int_24 addr, and hooks it to my_int24
1869 PUSH ES
1870 MOV AH, 35h
1871 MOV AL, 24h ;get critical error handler addr
1872 INT 21h
1873 MOV SAV_INT24_OFF, BX ;offset ip
1874 MOV SAV_INT24_SEG, ES ;seg cs
1875 POP ES
1876 PUSH DS ;save DS
1877 PUSH CS
1878 POP DS ;ds = cs
1879 MOV AH, 25h
1880 MOV AL, 24h
1881 MOV DX, OFFSET MY_INT24 ;now DS:DX contains the addr.
1882 INT 21h ;hook it to my_int24 routine
1883 POP DS ;restore ds
1884 RET
1885SAV_HOOK_INT24 ENDP
1886;
1887CSEG ENDS
1888 END
1889
1890 \ No newline at end of file
diff --git a/v4.0/src/CMD/XCOPY/XINITMSG.EQU b/v4.0/src/CMD/XCOPY/XINITMSG.EQU
new file mode 100644
index 0000000..cce6a5d
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/XINITMSG.EQU
@@ -0,0 +1,150 @@
1;*****************************************************************************
2; Message equates
3;*****************************************************************************
4CR equ 13
5LF equ 10
6BELL equ 7
7END_OF_MESSAGE equ 0
8ALPHA_D equ 'D'
9ALPHA_F equ 'F'
10NO_SUBST EQU 00H ;AN000;MSG PARAMETER SUBSTITUTION = 0
11PARM_SUBST_ONE EQU 01H ;AN000;MSG PARAMETER SUBSTITUTION = 1
12MSG_SER_CLASS EQU 00H ;AN000;MESSAGE SERVICE CLASS (RESERVED)
13EXT_ERR_CLASS EQU 01H ;AN000;DOS EXTENDED ERROR CLASS
14PARSE_ERR_CLASS EQU 02H ;AN000;PARSE ERROR CLASS
15UTILITY_MSG_CLASS EQU 0FFH ;AN000;UTILITY MESSAGE CLASS
16NO_INPUT EQU 00H ;AN000;NO INPUT CHARACTERS
17DOS_KEYB_INP EQU 01H ;AN000;KEYBOARD INPUT EXPECTED
18;******************************************************************************
19; The initialization messages
20;******************************************************************************
21;Init prompts for parameters
22
23MSG_CREATE_DIR EQU 4 ;AC000;FILE NAME OR DIRECTORY?
24
25MSG_TO_BEGIN EQU 5 ;AC000;PRESS ANY KEY TO BEGIN COPY
26
27MSG_F_D EQU 29 ;AN000;IS IT A FILE OR DIR NAME ?
28
29MSG_CR_LF_STR EQU 26 ;AN000;FOR CR,LF ONLY
30
31;Init error messages
32
33MSG_INCORRECT_DOS EQU 1 ;AC000;INCORRECT DOS VERSION
34
35MSG_INVALID_DRV EQU 11 ;AC000;INVALID DRIVE SPECIFICATION
36
37MSG_LONG_PATH EQU 6 ;AC000;PATH TOO LONG
38
39MSG_INVALID_PARM EQU 3 ;AC000;INVALID PARAMETER
40
41MSG_INV_NUM_PARM EQU 21 ;AC000;INVALID NUMBER OF PARAMETERS
42
43MSG_CYCLIC_COPY EQU 8 ;AC000;CANNOT PERFORM CYCLIC COPY
44
45MSG_INVALID_PATH EQU 7 ;AC000;INVALID PATH
46
47MSG_NOT_CREATE_DIR EQU 10 ;AC000;UNABLE TO CREATE DIRECTORY
48
49MSG_INVALID_DATE EQU 9 ;AC000;INVALID DATE
50
51MSG_RES_S_NAME EQU 12 ;AC000;CANNOT XCOPY FROM RESERVED DEVICE
52
53MSG_INSUF_MEMORY EQU 2 ;AC000;INSUFFICIENT MEMORY
54
55MSG_INV_SW EQU 35 ;AN004;DUPLICATE / INVALID SW FROM PARSE
56
57;******************************************************************************
58;Prompts for parameters -------------------------------------------------------
59;MSG_CREATE_DIR LABEL BYTE
60; DB CR, LF
61; DB 'Does %s specify a file name', CR,LF
62; DB 'or directory name on the target', CR,LF
63; DB '(F = file, D = directory)? '
64; ;DB
65; DB END_OF_MESSAGE
66;
67;------------------------------------------------------------------------------
68;MSG_TO_BEGIN LABEL BYTE
69; DB CR, LF
70; DB 'Press any key to begin copying file(s) '
71; ;DB
72; DB END_OF_MESSAGE
73;
74;------------------------------------------------------------------------------
75;MSG_F_D LABEL BYTE
76; DB 'FD '
77; ;DB
78; DB END_OF_MESSAGE
79;
80;Init error ------------------------------------------------------------------
81;MSG_INCORRECT_DOS LABEL BYTE
82; DB CR, LF
83; DB 'Incorrect DOS version'
84; ;DB
85; DB CR, LF, BELL, '$'
86;-----------------------------------------------------------------------------
87;MSG_INVALID_DRV LABEL BYTE
88; DB CR, LF
89; DB 'Invalid drive specification'
90; ;DB
91; DB CR, LF, BELL, END_OF_MESSAGE
92;-----------------------------------------------------------------------------
93;MSG_LONG_PATH LABEL BYTE
94; DB CR, LF
95; DB 'Path too long'
96; ;DB
97; DB CR, LF, BELL, END_OF_MESSAGE
98;------------------------------------------------------------------------------
99;MSG_INVALID_PARM LABEL BYTE
100; DB CR, LF
101; DB 'Invalid parameter'
102; ;DB
103; DB CR, LF, BELL, END_OF_MESSAGE
104;------------------------------------------------------------------------------
105;MSG_INV_NUM_PARM LABEL BYTE
106; DB CR, LF
107; DB 'Invalid number of parameters'
108; ;DB
109; DB CR, LF, BELL, END_OF_MESSAGE
110;------------------------------------------------------------------------------
111;MSG_CYCLIC_COPY LABEL BYTE
112; DB CR, LF
113; DB 'Cannot perform a cyclic copy'
114; ;DB
115; DB CR, LF, BELL, END_OF_MESSAGE
116;------------------------------------------------------------------------------
117;MSG_INVALID_PATH LABEL BYTE
118; DB CR, LF
119; DB 'Invalid path'
120; ;DB
121; DB CR, LF, BELL, END_OF_MESSAGE
122;------------------------------------------------------------------------------
123;MSG_NOT_CREATE_DIR LABEL BYTE
124; DB CR, LF
125; DB 'Unable to create directory'
126; ;DB
127; DB CR, LF, BELL, END_OF_MESSAGE
128;------------------------------------------------------------------------------
129;MSG_INVALID_DATE LABEL BYTE
130; DB CR, LF
131; DB 'Invalid date'
132; ;DB
133; DB CR, LF, BELL, END_OF_MESSAGE
134;------------------------------------------------------------------------------
135;MSG_RES_S_NAME LABEL BYTE
136; DB CR, LF
137; DB 'Cannot XCOPY from a reserved device'
138; ;DB
139; DB CR, LF, BELL, END_OF_MESSAGE
140;------------------------------------------------------------------------------
141;MSG_INSUF_MEMORY LABEL BYTE
142; DB CR, LF
143; DB 'Insufficient memory'
144; ;DB
145; DB CR, LF, BELL, END_OF_MESSAGE
146;------------------------------------------------------------------------------
147;******************* COPY RIGHT STATEMENT *************************************
148include copyrigh.inc
149;------------------------------------------------------------------------------
150;XCPYINIT_MSG_END LABEL BYTE
diff --git a/v4.0/src/CMD/XCOPY/XMAINMSG.EQU b/v4.0/src/CMD/XCOPY/XMAINMSG.EQU
new file mode 100644
index 0000000..76306f1
--- /dev/null
+++ b/v4.0/src/CMD/XCOPY/XMAINMSG.EQU
@@ -0,0 +1,46 @@
1;*****************************************************************************
2; Message equates
3;*****************************************************************************
4CR equ 13
5LF equ 10
6BELL equ 7
7END_OF_MESSAGE equ 0
8ALPHA_D equ 'D'
9ALPHA_F equ 'F'
10NO_SUBST EQU 00H ;AN000;MSG PARAMETER SUBSTITUTION = 0
11PARM_SUBST_ONE EQU 01H ;AN000;MSG PARAMETER SUBSTITUTION = 1
12PARM_SUBST_TWO EQU 02H ;AN000;MSG PARAMETER SUBSTITUTION = 2
13MSG_SER_CLASS EQU 00H ;AN000;MESSAGE SERVICE CLASS (RESERVED)
14EXT_ERR_CLASS EQU 01H ;AN000;DOS EXTENDED ERROR CLASS
15PARSE_ERR_CLASS EQU 02H ;AN000;PARSE ERROR CLASS
16UTILITY_MSG_CLASS EQU 0FFH ;AN000;UTILITY MESSAGE CLASS
17NO_INPUT EQU 00H ;AN000;NO INPUT CHARACTERS
18DOS_KEYB_INP EQU 01H ;AN000;KEYBOARD INPUT EXPECTED
19;******************************************************************************
20; XCOPY (MAIN) messages
21;*****************************************************************************
22; ERROR MESSAGES DEFINITION
23;
24MSG_INSUF_MEMORY EQU 2 ;AN005;INSUFFICIENT MEMORY
25MSG_ACCESS_DENIED EQU 13 ;AN000;
26MSG_TOO_MANY_OPEN EQU 14 ;AN000;
27MSG_GENERAL_FAIL EQU 15 ;AN000;
28MSG_SHARING_VIOL EQU 16 ;AN000;
29MSG_LOCK_VIOL EQU 17 ;AN000;
30MSG_PATH_NOT EQU 18 ;AN000;
31MSG_DISK_FULL EQU 19 ;AN000;
32MSG_COPY_ITSELF EQU 20 ;AN000;
33MSG_UNABLE_CREATE EQU 10 ;AN000;
34MSG_RES_T_NAME EQU 22 ;AN000;
35MSG_FILE_NOT_ERR EQU 23 ;AN000;
36MSG_FILE_CREATE_ERR EQU 24 ;AN000;
37MSG_READING_SOURCE EQU 25 ;AN000;
38MSG_CR_LF_STR EQU 26 ;AN000;
39MSG_FILES_COPIED EQU 27 ;AN000;
40S_PATH_FILE0 EQU 30 ;AN000;
41S_PATH_FILE1 EQU 31 ;AN000;
42DISPLAY_S_PATH EQU 32 ;AN000;
43P_S_PATH_FILE0 EQU 33 ;AN000;
44P_S_PATH_FILE1 EQU 34 ;AN000;
45;******************** END OF XCPYMAIN.MSG **************************************
46 \ No newline at end of file