Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2312 lines
78 KiB

  1. TITLE LDOPEN - Open and Delete Pathname primitives
  2. .xlist
  3. include kernel.inc
  4. include newexe.inc
  5. include tdb.inc
  6. include pdb.inc
  7. .list
  8. externFP AnsiUpper
  9. externFP Int21Handler
  10. externFP <lstrcpy>
  11. ifdef FE_SB
  12. externFP FarMyIsDBCSLeadByte
  13. externFP FarMyIsDBCSTrailByte
  14. endif
  15. ifdef WOW
  16. externFP GetDriveType
  17. endif
  18. ;** Equates for the Directory Table code
  19. DT_CURDIR EQU 1
  20. DT_WINDIR EQU 2
  21. ifndef WOW
  22. DT_SYSDIR EQU 3
  23. DT_APPDIR EQU 4
  24. MAX_SEARCH EQU 4
  25. else
  26. DT_SYS16DIR EQU 3
  27. DT_SYSDIR EQU 4
  28. DT_SYSWX86DIR EQU 5
  29. DT_APPDIR EQU 6
  30. MAX_SEARCH EQU 6
  31. endif
  32. DataBegin
  33. externB fInt21
  34. externB OutBuf
  35. externB szCannotFind1
  36. externB szCannotFind2
  37. externB szDiskCap
  38. externB LastDriveSwapped
  39. externB fNovell
  40. externB fBooting
  41. externW bufpos
  42. externW cBytesWinDir
  43. externW cBytesSysDir
  44. externW TopPDB
  45. externW curTDB
  46. externD lpWindowsDir
  47. externD lpSystemDir
  48. externD pSysProc
  49. externD pKeyProc
  50. externD pKeyProc1
  51. externD pSErrProc
  52. externW wMyOpenFileReent
  53. ;** These variables needed to implement the app dir searching
  54. externW loadTDB
  55. externW fLMDepth
  56. staticW myofint24,0
  57. ifdef WOW
  58. externD lpSystem16Dir
  59. externW cBytesSys16Dir
  60. externD lpSystemWx86Dir
  61. externW cBytesSysWx86Dir
  62. endif
  63. ;** Directory table for different search orders. Pgm Management-aware!!
  64. ; DIRTABLE struc holds pointers to previously searched paths so we don't
  65. ; repeat the path searches
  66. DIRTABLE STRUC
  67. dt_lpstr DD ?
  68. dt_wLen DW ?
  69. DIRTABLE ENDS
  70. dtDirTable LABEL DWORD
  71. public dtDirTable
  72. DB (SIZE DIRTABLE) * MAX_SEARCH DUP (0)
  73. ; These tables drive the search order loops, determining which paths
  74. ; to search in which order. The DOS/Novell path is always searched
  75. ; last.
  76. BootOrder LABEL BYTE
  77. DB DT_SYSDIR
  78. DB DT_WINDIR
  79. DB 0
  80. DefaultOrder LABEL BYTE
  81. DB DT_CURDIR
  82. DB DT_WINDIR
  83. ifdef WOW ; Search 16-bit system dir (\windir\system)
  84. DB DT_SYS16DIR
  85. endif
  86. DB DT_SYSDIR
  87. ifdef WOW ; Search Wx86 system dir (\windir\system32\Wx86)
  88. DB DT_SYSWX86DIR
  89. endif
  90. DB DT_APPDIR
  91. DB 0
  92. public BootOrder, DefaultOrder
  93. ;** Static variables
  94. szCurDir DB 128 DUP (0) ;Points to fully qualified current dir
  95. pCurDirName DW 0 ;Points to 8.3 filename
  96. wCurDirLen DW 0 ;Length of path minus 8.3 filename
  97. public pCurDirName, wCurDirLen, szCurDir
  98. ifdef WOW
  99. LastOFSearchEntry DW 0 ;Addr of last search table entry used
  100. ;for continuing the search.
  101. OFContinueSearch DW 0 ;1 means continue last search
  102. public LastOFSearchEntry, OFContinueSearch
  103. endif
  104. DataEnd
  105. sBegin CODE
  106. assumes CS,CODE
  107. assumes DS,NOTHING
  108. assumes ES,NOTHING
  109. externNP MyUpper
  110. externNP PathDrvDSDX
  111. externNP real_DOS
  112. ifdef FE_SB
  113. externNP MyIsDBCSLeadByte
  114. externNP MyIsDBCSTrailByte
  115. endif
  116. ; These constants are the same as the OF_* values, but are a single byte
  117. ; for efficiency
  118. fReOpen equ 10000000b
  119. fExist equ 01000000b
  120. fPrompt equ 00100000b
  121. fCreate equ 00010000b
  122. fCancel equ 00001000b
  123. fVerify equ 00000100b
  124. fSearch equ 00000100b
  125. fDelete equ 00000010b
  126. fParse equ 00000001b
  127. ;** Flags to InternalOpenFile
  128. IOF_SYSTEM EQU 1
  129. ;!!!!!! Everything from here to the next !!!!! rewritten Aug 2-5 1991 [jont]
  130. ;-----------------------------------------------------------------------;
  131. ; OpenFile
  132. ; ;
  133. ; OpenFile: Opens the given file (with LOTS of options) ;
  134. ; The search order is defined above in the data section and is ;
  135. ; table-driven. ;
  136. ; ;
  137. ; Arguments: ;
  138. ; ParmD lpstrSourceName ;
  139. ; ParmD lpOFStruct ;
  140. ; ParmW Command ;
  141. ; ;
  142. ; Returns: ;
  143. ; AX = file handle ;
  144. ; ;
  145. ; Error Returns: ;
  146. ; AX = error code ;
  147. ; ;
  148. ; Registers Preserved: ;
  149. ; DI,SI,DS ;
  150. ; ;
  151. ; Registers Destroyed: ;
  152. ; ;
  153. ; Calls: ;
  154. ; ;
  155. ; History: ;
  156. ; ;
  157. ; Mon Oct 12, 1987 09:06:05p -by- David N. Weise [davidw] ;
  158. ; Added this nifty coment block. ;
  159. ; ;
  160. ; August 5, 1991 -by- Jon Thomason [jont] ;
  161. ; Rewrote large sections. Made it table-driven to allow ;
  162. ; changing search paths. Made it return extended error codes ;
  163. ; for all file not found errors. Generally made it into a ;
  164. ; humanly-readable module. ;
  165. ; ;
  166. ;-----------------------------------------------------------------------;
  167. cProc IOpenFile, <PUBLIC,FAR>, <si,di,ds>
  168. parmD lpSrcFile ;String pointing to filename
  169. parmD lpOFStruct ;Points to OFSTRUCT
  170. parmW wFlags ;LowB is DOS flags, High is OF flags
  171. localD lpDestDir ;Points to dest dir in OFSTRUCT
  172. cBegin
  173. SetKernelDS
  174. ;** If the file is to be reopened, do it
  175. test BYTE PTR wFlags[1],fReopen ;Reopen file?
  176. jz IOF_NoReopen ;No
  177. les di,lpOFStruct ;Point to structure
  178. cCall ReOpenFile, <es,di,wFlags> ;Reopen the file
  179. jmp IOF_End ;Done
  180. IOF_NoReopen:
  181. ifdef WOW
  182. ; Reset LastOFSearchEntry if we're not continuing an earlier search
  183. cmp OFContinueSearch,0
  184. jne @F
  185. mov LastOFSearchEntry,0
  186. @@:
  187. endif
  188. ;** Get a pointer into the OFSTRUCT
  189. mov di,WORD PTR lpOFStruct[0] ;Point to structure
  190. lea di,[di].opFile ;Point to string
  191. mov WORD PTR lpDestDir[0],di ;Save in temp variable
  192. mov di,WORD PTR lpOFStruct[2] ;Get the selector
  193. mov WORD PTR lpDestDir[2],di
  194. ;** Parse the filename and prepare for searching
  195. mov bx,dataOFFSET szCurDir ;Point to dest string
  196. les si,lpSrcFile ;Point to source string
  197. if 0
  198. krDebugOut DEB_WARN,"WOW16 IOpenFile:Filename @ES:SI"
  199. endif
  200. cCall ParseFileName, <es,si,ds,bx,wFlags>
  201. ;** Check for error
  202. or ax,ax ;Error?
  203. jnz @F ;No
  204. mov ax,0 ;Flag that this is a parse error
  205. mov bx,dataOFFSET szCurDir ;pass lpSrcFile as error string
  206. cCall ErrorReturn, <lpOFStruct,ds,bx,lpSrcFile,wFlags,ax>
  207. jmp IOF_End ;Get out
  208. @@:
  209. ;** If they just wanted to parse, fill in the structure and return
  210. test BYTE PTR wFlags[1],fParse ;Parse only?
  211. jz @F ;No, skip this
  212. mov bx,dataOFFSET szCurDir ;Point to full pathname with DX:BX
  213. mov dx,ds
  214. xor ax,ax ;No file handle
  215. jmp IOF_DoCopy ;Mimic successful file open
  216. @@:
  217. ;** Save return values for future use
  218. mov pCurDirName,bx ;Points to 8.3 name
  219. mov wCurDirLen,cx ;Length of path portion
  220. ;** See if we should path search (flag returned in DX)
  221. or dx,dx
  222. jz IOF_InitSearch ;Do the search
  223. ;** Try to open the file without searching any other dirs
  224. les bx,lpDestDir ;Point to dest dir
  225. mov di,dataOFFSET dtDirTable ;Point to the start of the DirTable
  226. cCall GetPath, <DT_CURDIR,di,es,bx> ;Dest dir returned in ES:BX
  227. cCall OpenCall, <es,bx,wFlags> ;Try to open it
  228. jc @F
  229. jmp IOF_Success
  230. @@: jmp IOF_Error ;File found but problem opening
  231. ;** Point to the proper search order
  232. IOF_InitSearch:
  233. SetKernelDS
  234. ifdef WOW
  235. cmp OFContinueSearch,0
  236. je @F
  237. mov OFContinueSearch,0 ;consumed the flag, reset it
  238. mov si,LastOFSearchEntry
  239. or si,si ;Were we searching at all?
  240. jnz IOF_WereSearching ;Yes
  241. jmp short IOF_FileNotFound ;No searching, so give up now.
  242. IOF_WereSearching:
  243. cmp si,-1 ;Already tried SearchPath?
  244. jne IOF_RestartSearch ;No, pick up where we left off in order
  245. IOF_FileNotFound:
  246. mov ax,2 ;SearchPath found it last time, so
  247. jmp IOF_Error ;it won't find a different one this
  248. ;time, se we return File not found
  249. IOF_RestartSearch:
  250. inc si
  251. mov LastOFSearchEntry,si
  252. mov al,[si]
  253. cbw
  254. or al,al
  255. mov di,dataOFFSET dtDirTable;Point to the start of the DirTable
  256. jnz IOF_SearchLoop ;Pick up with next in search order
  257. jmp short IOF_SearchPath ;Restarting after last in search
  258. ;order, so try DOS/Novell path.
  259. @@:
  260. endif
  261. mov si,dataOFFSET DefaultOrder
  262. cmp fBooting,0 ;Booting?
  263. jz IOF_DoSearch ;No
  264. mov si,dataOFFSET BootOrder
  265. IOF_DoSearch:
  266. ifdef WOW
  267. mov LastOFSearchEntry,si
  268. endif
  269. mov al,[si] ;Get the first search code
  270. cbw
  271. mov di,dataOFFSET dtDirTable ;Point to the start of the DirTable
  272. ;** Loop through until we have no more directories to search or
  273. ;** until the file is found
  274. IOF_SearchLoop:
  275. ;** Get the path and filename for this index entry
  276. les bx,lpDestDir ;Point to dest dir
  277. cCall GetPath, <ax,di,es,bx> ;Returns pointer to dest dir in ES:BX
  278. or bx,bx ;Duplicate dir?
  279. jz IOF_Continue ;Yes, skip this
  280. ;** Try to open the file
  281. cCall OpenCall, <es,bx,wFlags> ;Try to open it
  282. jnc IOF_Success ;File was found
  283. cmp ax,3 ;Errors 3 or less mean file not found
  284. ja IOF_Error ;File found but problem opening
  285. ;** File not found, so try next path if any
  286. IOF_Continue:
  287. add di,SIZE DIRTABLE ;Bump to next DirTable entry
  288. inc si ;Bump to next code in list
  289. ifdef WOW
  290. mov LastOFSearchEntry,si
  291. endif
  292. mov al,[si] ;Get this code
  293. cbw ;Make it a WORD
  294. or al,al ;Done?
  295. jnz IOF_SearchLoop ;No
  296. ;** Try the DOS/Novell path next
  297. ifdef WOW
  298. IOF_SearchPath:
  299. xor si,si
  300. dec si
  301. mov LastOFSearchEntry,si
  302. endif
  303. les di,lpDestDir ;Point to the dest dir
  304. mov si,pCurDirName ;Point to the 8.3 name
  305. cCall SearchFullPath, <ds,si,es,di,wFlags>
  306. jc IOF_Error ;Not found here either
  307. ;** On SUCCESS, we come here. Delete the file and close if
  308. ;** necessary
  309. IOF_Success:
  310. mov bx,WORD PTR lpDestDir[0] ;Point to filename with DX:BX
  311. mov dx,WORD PTR lpDestDir[2]
  312. IOF_DoCopy:
  313. les si,lpOFStruct ;Point to OFSTRUCT
  314. cCall SuccessCleanup, <dx,bx,es,si,wFlags,ax> ;Finish up
  315. jmp SHORT IOF_End
  316. ;** On ERROR, complete the structure and return the error code
  317. IOF_Error:
  318. les si,lpOFStruct
  319. mov bx,dataOFFSET szCurDir ;Point to current dir
  320. cCall ErrorReturn, <es,si,ds,bx,ds,pCurDirName,wFlags,ax>
  321. IOF_End:
  322. cEnd
  323. ;---------------------------------------------------------------------------
  324. ; ReOpenFile
  325. ;
  326. ; Does a fast reopen of a file that has already been opened.
  327. ; Returns proper value in AX for return from OpenFile
  328. ;
  329. ; Trashes everything but si,di,ds
  330. ;
  331. ;---------------------------------------------------------------------------
  332. cProc ReOpenFile, <PUBLIC,NEAR>, <si,di,ds>
  333. parmD lpStruct ;LPOFSTRUCT parameter
  334. parmW wFlags ;OpenFile flags
  335. localW hFile
  336. cBegin
  337. ;** Set up for the reopen
  338. lds si,lpStruct ;Point to the OFSTRUCT
  339. lea dx,[si].opFile ;DS:DX -> path
  340. call PathDrvDSDX ;Make sure DRV letter is valid
  341. jc ROF_SetDrvErr
  342. ;** Set up for either an OPEN or a CREATE
  343. mov al,BYTE PTR wFlags[0] ;Get the access bits
  344. test BYTE PTR wFlags[1],fCreate ;Create file or open
  345. jnz ROF_CreateIt ;In create case, we just do it
  346. mov ah,3dh ;Open file call
  347. jmp SHORT @F
  348. ROF_CreateIt:
  349. mov ah,3ch ;Create file call
  350. @@: xor cx,cx ;Default file attributes
  351. call real_DOS ;Skip overhead of Int21Handler
  352. jnc ROF_10 ;Continue on no error
  353. jmp SHORT ROF_GetError ;Get out on error
  354. ROF_SetDrvErr:
  355. lds si,lpStruct ;Point to the OFSTRUCT
  356. mov [si].opXtra,ax ;In OFSTRUCT, this is the error code
  357. mov ax,-1 ;Error return
  358. jmp ROF_End ;Error
  359. ROF_10: mov bx,ax ;Get handle
  360. mov hFile,ax ;Save handle for later
  361. ifdef WOW
  362. xor cx,cx
  363. xor dx,dx
  364. push ds
  365. SetKernelDS ds
  366. cmp fLMdepth,cx ; Called From Loader ?
  367. pop ds
  368. UnSetKernelDS ds
  369. jnz @f ; Yes -> Ignore Date/Time
  370. endif
  371. mov ax,5700h ;Get time and date of file
  372. DOSCALL
  373. @@:
  374. mov ax,bx ;Put file handle back in ax
  375. test BYTE PTR wFlags[1],fVerify ;Should we test time/date?
  376. jz ROF_VerifyOK
  377. cmp [si].opDate,dx ;Same date as original?
  378. jnz ROF_ErrorClose ;No
  379. cmp [si].opTime,cx ;Same time as original?
  380. jnz ROF_ErrorClose ;No
  381. ROF_VerifyOK:
  382. mov es:[si].opTime,cx ;Save the date and time
  383. mov es:[si].opDate,dx
  384. ;** See if we were supposed to just get the name, or find file
  385. test BYTE PTR wFlags[1],fDelete or fExist
  386. jz ROF_Done ;Nope, we're done
  387. ;** If the user specified OF_DELETE, we don't want
  388. ;** the file open, so close it here.
  389. ;** NOTE: THIS CODE IS DUPLICATED IN FillOFStruct()!!!!
  390. mov bx,hFile ;Get handle
  391. mov ah,3Eh ;Close the file
  392. DOSCALL
  393. ;** See if we should delete the file
  394. test BYTE PTR wFlags[1],fDelete
  395. jz ROF_Done ;Nope, we're done
  396. smov ds,es ;DS:DX points to full pathname
  397. UnSetKernelDS
  398. lea dx,[si].opFile
  399. mov ah,41h ;Delete the file
  400. DOSCALL
  401. jnc ROF_Done ;Return the file handle for compat.
  402. ;** Get extended error always
  403. ROF_GetError:
  404. mov ah,59h ;See if there is an extended error
  405. xor bx,bx
  406. push bp ;GetExtendedError trashes regs
  407. push si
  408. push es
  409. DOSCALL
  410. pop es
  411. pop si
  412. pop bp
  413. mov [si].opXtra,ax ;In OFSTRUCT, this is the error code
  414. mov ax,-1 ;Error return
  415. jmp SHORT ROF_End
  416. ROF_ErrorClose:
  417. mov bx,hFile ;Get the file handle
  418. mov ah,3Eh ;Close the bogus file
  419. DOSCALL
  420. mov ax,-1 ;Error return value
  421. lds si,lpStruct ;Point to the OFSTRUCT
  422. mov [si].opXtra,0 ;Non-DOS error
  423. jmp SHORT ROF_End ;Get out
  424. ROF_Done:
  425. mov ax,hFile ;Proper return value for OpenFile
  426. ROF_End:
  427. cEnd
  428. ;----------------------------------------------------------------------------
  429. ; ParseFileName
  430. ;
  431. ; Prepares to do the various file searches by returning a pointer
  432. ; to the fully qualified path and to the "pure" filename
  433. ; (just the 8.3 name).
  434. ;
  435. ; Returns:
  436. ; AX = TRUE/FALSE function successful (if F, nothing else valid)
  437. ; BX points to start of 8.3 filename
  438. ; CX = Length of path portion of filename
  439. ; DX = TRUE/FALSE: Indicates whether path should be searched
  440. ;
  441. ;----------------------------------------------------------------------------
  442. cProc ParseFileName, <PUBLIC,NEAR>, <si,di,ds>
  443. parmD lpSrcName ;Passed in pathname
  444. parmD lpDestName ;String to receive pathname
  445. parmW wFlags ;Command WORD to OpenFile
  446. localW wPathLen ;Length of path portion of filename
  447. cBegin
  448. ;** Get the fully qualified pathname in lpDestName
  449. lds si,lpSrcName ;DS:SI points to source file
  450. les di,lpDestName ;ES:DI points to file buffer
  451. call ParseFile ;Form a complete name in buffer
  452. ; Returns dir len in CX when failing
  453. or ax,ax ;Successful?
  454. jz PFN_End ;No, get out
  455. mov wPathLen,dx ;Save length of path (no 8.3)
  456. ;** This section handles the fSearch flag. This flag is used to
  457. ;** do a path search even when we have a path in front of
  458. ;** the filename.
  459. test BYTE PTR wFlags[1],fSearch ;Do search even with path?
  460. jz PF_NoSearch ;No.
  461. xor di,di ;Indicate no slashes
  462. PF_NoSearch:
  463. ;** Convert the filename to OEM
  464. lds si,lpDestName ;Point to full path
  465. cCall MyAnsiToOem,<ds,si,ds,si>
  466. ;** Return arguments
  467. mov ax,1 ;Success
  468. mov bx,WORD PTR lpDestName[0] ;Get the offset of the string
  469. mov cx,wPathLen ;Length of path portion of name
  470. add bx,cx ;Point to start of string
  471. inc bx ;Skip slash
  472. mov dx,di ;Slashes/path search flag
  473. PFN_End:
  474. cEnd
  475. ;----------------------------------------------------------------------------
  476. ; GetPointer
  477. ;
  478. ; Given an index number, returns a pointer to the path associated
  479. ; with this index and its length
  480. ;
  481. ; Returns the lpstr in ES:BX, length in CX
  482. ;
  483. ; Depends on the order of the DT_* indices
  484. ; Depends on Kernel's DS being set, does not trash it
  485. ;
  486. ;----------------------------------------------------------------------------
  487. cProc GetPointer, <PUBLIC,NEAR>, <si,di>
  488. parmW wIndex ;Index is from search order table
  489. cBegin
  490. CheckKernelDS
  491. ReSetKernelDS
  492. ;** Decode the index numbers
  493. mov ax,wIndex ;Get the index
  494. dec ax ;DT_CURDIR?
  495. jz GT_CURDIR
  496. dec ax ;DT_WINDIR?
  497. jz GT_WINDIR
  498. ifndef WOW
  499. dec ax ;DT_SYSDIR?
  500. jz GT_SYSDIR
  501. else
  502. dec ax ;DT_SYS16DIR?
  503. jz GT_SYS16DIR
  504. dec ax ;DT_SYSDIR?
  505. jz GT_SYSDIR
  506. dec ax ;DT_SYSWX86DIR?
  507. jz GT_SYSWX86DIR
  508. endif
  509. ; Must be DT_APPDIR
  510. ;** Find the app's dir
  511. IF KDEBUG
  512. cmp fBooting,0 ;Booting?
  513. jz @F ;No, whew!
  514. int 1 ;No app dir during boot process
  515. int 1
  516. @@:
  517. ENDIF
  518. ;** Figure out if we should use curTDB or loadTDB. This is
  519. ;** determined by the number of times LoadModule has recursed.
  520. ;** We only use the loadTDB pointer if we're in LoadModule the
  521. ;** second time and the pointer is not zero. Otherwise, we
  522. ;** use the curTDB pointer. If we don't do this check, we
  523. ;** end up getting the path of the app calling LoadModule
  524. cmp fLMDepth,2 ;In LoadModule 2 times?
  525. jb GT_UseCurTDB ;Yes, use curTDB
  526. mov ax,LoadTDB ;Get loadTDB
  527. or ax,ax ;NULL?
  528. jnz GT_UseLoadTDB ;No, assume it's OK
  529. ;** Get a pointer to the path stored in the module database
  530. GT_UseCurTDB:
  531. mov ax,curTDB ;Get the TDB pointer
  532. GT_UseLoadTDB:
  533. mov es,ax ;Point with DS
  534. mov es,es:[TDB_pModule] ;Point to the module database
  535. IFDEF ROM
  536. ; if this is in ROM, then return 0 in CX
  537. ; makes no sense to get the app's dir, if app is in ROM
  538. test es:[ne_flags], NEMODINROM
  539. jz @f
  540. xor cx, cx
  541. jmp SHORT GT_Done
  542. @@:
  543. ENDIF
  544. mov di,es:[0ah] ;Points to EXE path string (sort of)
  545. ; (High word of CRC in exe hdr)
  546. ;** Copy the entire string into the buffer
  547. add di,8 ;Move past data garbage
  548. push di ;Save start of string
  549. cCall GetPureName ;ES:DI points just after the '\'
  550. dec di ;ES:DI points to '\'
  551. pop bx ;ES:BX points to start of string
  552. mov cx,di ;Compute length of path, not filename
  553. sub cx,bx ; (not including \)
  554. jmp SHORT GT_Done
  555. ;** Get the current directory pointer and length
  556. GT_CURDIR:
  557. smov es,ds ;ES:BX points to szCurDir
  558. mov bx,dataOFFSET szCurDir
  559. mov cx,wCurDirLen ;Get path length
  560. jmp SHORT GT_Done
  561. GT_WINDIR:
  562. les bx,lpWindowsDir ;Point to windir
  563. mov cx,cBytesWinDir
  564. jmp SHORT GT_Done
  565. GT_SYSDIR:
  566. les bx,lpSystemDir ;Point to sysdir
  567. mov cx,cBytesSysDir
  568. ifdef WOW
  569. jmp SHORT GT_Done
  570. GT_SYS16DIR:
  571. les bx,lpSystem16Dir ;Point to sys16dir
  572. mov cx,cBytesSys16Dir
  573. jmp SHORT GT_Done
  574. GT_SYSWX86DIR:
  575. les bx,lpSystemWx86Dir
  576. mov cx,cBytesSysWx86Dir
  577. ;jmp SHORT GT_Done
  578. endif ;WOW
  579. GT_Done:
  580. cEnd
  581. ;----------------------------------------------------------------------------
  582. ; GetPath
  583. ;
  584. ; Gets the path associated with the given index. The 8.3 filename
  585. ; is appended to the end of the path and this is copied into the
  586. ; destination directory. A pointer to this directory is returned
  587. ; in ES:BX or BX is NULL if the directory to be searched would be
  588. ; a duplicate.
  589. ;
  590. ; Assumes (and does not trash) kernel's DS
  591. ;
  592. ; Calls: GetPointer
  593. ;
  594. ;----------------------------------------------------------------------------
  595. cProc GetPath, <PUBLIC,NEAR>, <si,di>
  596. parmW wIndex ;Index from search order table
  597. parmW pDirTable ;Points to current DIRTABLE entry
  598. parmD lpDest ;Place to copy filename
  599. cBegin
  600. CheckKernelDS
  601. ;** Gets the pointer and length of the requested string
  602. cCall GetPointer, <wIndex> ;lpstr in ES:BX, len in CX
  603. IFDEF ROM
  604. or cx, cx ; if in ROM && APPDIR
  605. jnz @f
  606. xor bx, bx
  607. jmp SHORT GP_End
  608. @@:
  609. ENDIF
  610. ;** Save it in the table
  611. mov di,pDirTable ;Point to the table entry
  612. mov WORD PTR [di].dt_lpstr[0],bx
  613. mov WORD PTR [di].dt_lpstr[2],es
  614. mov [di].dt_wLen,cx
  615. ;** Check for duplicates
  616. mov si,bx ;Point to string with SI
  617. mov bx,dataOFFSET dtDirTable ;Point to the start of the table
  618. GP_Loop:
  619. cmp bx,di ;Checked everything before us yet?
  620. je GP_Done ;Yes
  621. ;** Compare the strings
  622. cmp cx,[bx].dt_wLen ;Compare lengths
  623. jne GP_Continue ;No dup here
  624. mov dx,cx ;Save len in DX
  625. push si
  626. push di
  627. push ds
  628. les di,ds:[di].dt_lpstr ;Point to the strings to be compared
  629. lds si,ds:[bx].dt_lpstr
  630. repe cmpsb ;Compare the strings
  631. pop ds
  632. pop di
  633. pop si
  634. or cx,cx ;At end of string?
  635. jz GP_FoundMatch ;Yes, we matched so ignore this string
  636. mov cx,dx ;Get len back in CX
  637. GP_Continue:
  638. add bx,SIZE DIRTABLE ;Bump to next table entry
  639. jmp GP_Loop
  640. GP_FoundMatch:
  641. mov WORD PTR [di].dt_lpstr[0],0 ;Null out this entry
  642. mov WORD PTR [di].dt_lpstr[2],0
  643. mov [di].dt_wLen,0
  644. xor bx,bx ;Return NULL
  645. jmp SHORT GP_End
  646. GP_Done:
  647. ;** Copy the string in
  648. push ds ;Save DS around this
  649. lds si,[di].dt_lpstr ;Return ES:BX pointing to string
  650. les di,lpDest ;Point to buffer to copy string to
  651. mov bx,di ;Point with BX to struct
  652. rep movsb ;Copy the strings
  653. pop ds ;Restore KERNEL's DS
  654. ;** Put a '\' only if needed
  655. IFDEF FE_SB
  656. push si
  657. push di
  658. mov si,word ptr lpDest[0] ;es:si -> string address
  659. dec di ;di points to the last valid byte
  660. call MyIsDBCSTrailByte ;the last byts a DBCS trailing byte?
  661. pop di
  662. pop si
  663. jnc GP_DoSlash ;yes, go ahead to append a '\'
  664. ;no, fall through
  665. ENDIF
  666. cmp BYTE PTR es:[di - 1],'\';Terminating slash?
  667. je GP_SkipSlash ;Yes
  668. cmp BYTE PTR es:[di - 1],'/';Terminating slash?
  669. je GP_SkipSlash ;Yes
  670. GP_DoSlash:
  671. mov al,'\' ;Get the slash
  672. stosb ; and write it
  673. GP_SkipSlash:
  674. ;** Copy the filename
  675. mov si,pCurDirName ;Point to the 8.3 filename
  676. call strcpyreg
  677. ;GP_83Loop:
  678. ; lodsb ;Get the char
  679. ; stosb ; and write it
  680. ; or al,al ;Done?
  681. ; jnz GP_83Loop ;Nope
  682. ;Returns ES:BX points to filename
  683. GP_End:
  684. cEnd
  685. ;----------------------------------------------------------------------------
  686. ; OpenCall
  687. ;
  688. ; Does the open/create file call. The file is either opened
  689. ; or created. The handle or the error code is returned.
  690. ; The extended error code is returned only if the error was not
  691. ; that the file or path was not found (errors 2 & 3).
  692. ; Carry is set on error.
  693. ;
  694. ;----------------------------------------------------------------------------
  695. cProc OpenCall, <PUBLIC,NEAR>, <si,di,ds>
  696. parmD lpString ;String to open
  697. parmW wFlags ;OpenFile flags
  698. localW wInt21AX ;Int 21 AX value
  699. cBegin
  700. ;** HACK to allow SearchPath to use this call.
  701. ;** If wFlags is -1, look for flags preset in AX
  702. cmp wFlags,-1 ;wFlags?
  703. jnz OC_Normal ;Yes, proceed normally
  704. mov wInt21AX,ax ;Save these flags
  705. jmp SHORT OC_10 ; and go on
  706. ;** Set up for either an OPEN or a CREATE
  707. OC_Normal:
  708. mov al,BYTE PTR wFlags[0] ;Get the access bits
  709. test BYTE PTR wFlags[1],fCreate ;Create file or open
  710. jnz OC_CreateIt ;In create case, we just do it
  711. mov ah,3dh ;Open file call
  712. mov wInt21AX,ax ;Save in temp var
  713. jmp SHORT OC_10
  714. OC_CreateIt:
  715. mov ah,3ch ;Create file call
  716. and al,3 ;Strip incompatbile share bits, etc.
  717. mov wInt21AX,ax ;Save it
  718. jmp SHORT OC_DoDOSCall ;Just do it in create case
  719. OC_10: SetKernelDS
  720. cmp fNovell,0 ;On Novell?
  721. je OC_DoDOSCall ;No, just do normal stuff
  722. ;** We do a Get Attribute call instead of trying to open the file
  723. ;** because doing a normal file open on Novell causes them
  724. ;** to search their entire path.
  725. lds dx,lpString ;Get the pathname
  726. mov ax,4300h ;Get file attributes
  727. DOSCALL ;Does the file exist?
  728. jc OC_NotThere ;No
  729. ;** Try to open the file here. In case of Novell, we already know
  730. ;** it's here, so now open it
  731. OC_DoDOSCall:
  732. xor cx,cx ;Normal files ONLY!!
  733. mov ax,wInt21AX ;Get function code + access flags
  734. lds dx,lpString ;Get the pathname
  735. DOSCALL ;Try to open the file
  736. jc OC_NotThere ;File can't be opened
  737. jmp SHORT OC_FileOpened ;Success
  738. OC_NotThere:
  739. cmp ax,3 ;Errors 2 & 3 are file not found
  740. jbe OC_NoExtError ;No extended error for file not found
  741. SetKernelDS
  742. cmp wMyOpenFileReent, 0 ;No ext err for MyOpenFile
  743. jnz OC_NoExtError
  744. mov ah,59h ;See if there is an extended error
  745. xor bx,bx
  746. push bp ;GetExtendedError trashes bp
  747. DOSCALL
  748. pop bp
  749. OC_NoExtError:
  750. stc ;Return error
  751. OC_FileOpened: ;CY must be clear here on success
  752. cEnd
  753. ;----------------------------------------------------------------------------
  754. ; SearchFullPath
  755. ;
  756. ; Searches the full DOS/Novell path for the file
  757. ;
  758. ; Returns the file handle on success or the error code on failure
  759. ; Carry set on error
  760. ;
  761. ;----------------------------------------------------------------------------
  762. cProc SearchFullPath, <PUBLIC,NEAR>, <si,di,ds>
  763. parmD lpSource ;8.3 filename
  764. parmD lpDest ;Place to copy pathname
  765. parmW wFlags ;OpenFile flags
  766. localW wInt21AX
  767. cBegin
  768. ;** Get the AX WORD for the DOS call
  769. mov al,BYTE PTR wFlags[0] ;Get the access bits
  770. test BYTE PTR wFlags[1],fCreate ;Create file or open?
  771. mov ah,3dh ;Default to open
  772. jz @F
  773. mov ah,3ch ;Create call
  774. @@: mov wInt21AX,ax ;Save it for later
  775. ;** Use SearchPath() to find the file for us
  776. push ds ;Save DS across this
  777. les di,lpDest ;Point to usable dest buffer
  778. lds si,lpSource ;Point to source string
  779. UnsetKernelDS
  780. cCall <FAR PTR SearchPath>,<ds,si,es,di,ax>
  781. pop ds
  782. ResetKernelDS
  783. cmp ax,-1
  784. jne SFP_FoundIt ;Found the file
  785. mov ax,bx ;Get error code from SearchPath
  786. cmp ax,3 ;Not found?
  787. ja SFP_Error ;Found but error
  788. ;** Now try the Novell path if it's there
  789. cmp fNovell,0 ;On Novell?
  790. je SFP_Error ;Nope. Nothing more to try so error
  791. lds dx,lpSource ;Point to 8.3 filename
  792. UnsetKernelDS
  793. xor cx,cx ;Normal file type
  794. mov ax,wInt21AX ;Get open or create call plus attrs
  795. DOSCALL ;Do it
  796. jc SFP_Error ;Didn't find it
  797. SFP_FoundIt:
  798. clc
  799. jmp SHORT SFP_End
  800. SFP_Error:
  801. stc
  802. SFP_End: ;Carry should be set/clear correctly
  803. cEnd
  804. ;----------------------------------------------------------------------------
  805. ; SuccessCleanup
  806. ;
  807. ; Builds the OFSTRUCT structure on a successful open.
  808. ; Closes and deletes file if requested.
  809. ;
  810. ;----------------------------------------------------------------------------
  811. cProc SuccessCleanup, <PUBLIC,NEAR>, <si,di,ds>
  812. parmD lpGoodPathName ;Successful path name
  813. parmD lpOFStruct ;OFSTRUCT param to OpenFile
  814. parmW wFlags ;OpenFile flags
  815. parmW hFile ;File handle
  816. cBegin
  817. ;** Compute the length of the string and OFSTRUCT
  818. les di,lpGoodPathName ;Point to the new pathname
  819. xor al,al ;Get a zero byte
  820. xor cx,cx ;Up to 64K
  821. dec cx
  822. repne scasb ;Search for the zero byte
  823. neg cx
  824. mov ax,cx ;Get a copy in AX
  825. add ax,(SIZE OPENSTRUC) - 3 ;Length of structure including string
  826. ;** Copy the successful pathname into the OFSTRUCT if necessary
  827. dec cx ;This now is string + zero byte len
  828. les di,lpOFStruct ;Point to dest buffer
  829. lea di,[di].opFile
  830. cmp di,WORD PTR lpGoodPathName[0] ;Offsets the same?
  831. jne FOF_DoCopy ;No, do it
  832. mov dx,es ;Compare sels
  833. cmp dx,WORD PTR lpGoodPathName[2] ;Same?
  834. je FOF_NoCopy ;Yes, no copy needed
  835. FOF_DoCopy:
  836. lds si,lpGoodPathName ;Point to successful path again
  837. UnSetKernelDS
  838. rep movsb ;Copy it
  839. FOF_NoCopy:
  840. ;** Fill out remainder of OFSTRUCT
  841. les si,lpOFStruct ;Point to OFSTRUCT with ES:SI
  842. lea di,[si].opFile ; and to the pathname with ES:DI
  843. mov es:[si].opXtra,0 ;Zero the error
  844. mov es:[si].opLen,al ;Save structure length
  845. call AreBooting ;AreBooting checks Int21 hooks inst
  846. mov ah,1 ;Always booting from hard drive
  847. jz FO_NoCheckDrive ;Int 21 hooks NOT installed yet
  848. mov al,es:[di] ;ES:DI points to string
  849. or al,20H ;Force it lowercase
  850. sub al,'a' ;Drive number, zero based
  851. cbw
  852. mov di,ax ;Drive number in DI
  853. call IsFloppy ;Returns floppy status in ZF
  854. mov ah,0 ;Zero in case it's a floppy
  855. jz FO_NoCheckDrive ;Must be a floppy disk
  856. inc ah ;Non-removable media
  857. FO_NoCheckDrive:
  858. mov es:[si].opDisk,ah ;Tell 'em the type of disk
  859. ;** Get the current file date and time
  860. mov bx,hFile ;Get file handle
  861. mov ax,5700h ;Get date and time
  862. ifdef WOW
  863. xor cx,cx
  864. xor dx,dx
  865. push ds
  866. SetKernelDS ds
  867. cmp fLMdepth,cx ; Called From Loader ?
  868. pop ds
  869. UnSetKernelDS ds
  870. jnz @f ; Yes -> Ignore Date/Time
  871. endif
  872. DOSCALL
  873. @@:
  874. mov es:[si].opTime,cx ;Save the date and time
  875. mov es:[si].opDate,dx
  876. ;** See if we were supposed to just get the name, or find file
  877. test BYTE PTR wFlags[1],fExist OR fDelete
  878. jz FO_Done ;Nope, we're done
  879. ;** If the user specified OF_EXIST or OF_DELETE, we don't want
  880. ;** the file open, so close it here
  881. ;** NOTE: THIS CODE IS DUPLICATED IN ReopenFile()!!!!
  882. mov bx,hFile ;Get the handle
  883. mov ah,3Eh ;Close the file
  884. DOSCALL
  885. ;We leave the bogus value in hFile
  886. ; for 3.0 compatibility
  887. ;** If OF_DELETE is set, we simply delete the file
  888. test BYTE PTR wFlags[1],fDelete
  889. jz FO_Done
  890. smov ds,es ;DS:DX points to full pathname
  891. UnSetKernelDS
  892. lea dx,[si].opFile
  893. mov ah,41h ;Delete the file
  894. DOSCALL
  895. mov ax,1 ;TRUE return value
  896. jnc FO_Done ;For 3.0 compatiblity
  897. mov ah,59h ;See if there is an extended error
  898. xor bx,bx
  899. push bp ;GetExtendedError trashes regs
  900. push si
  901. DOSCALL
  902. pop si
  903. pop bp
  904. mov [si].opXtra,ax ;In OFSTRUCT, this is the error code
  905. mov ax,-1 ;Error return
  906. jmp SHORT FO_END
  907. FO_Done:
  908. mov ax,hFile ;Proper return value for OpenFile
  909. FO_End:
  910. cEnd
  911. ;----------------------------------------------------------------------------
  912. ; ErrorReturn
  913. ;
  914. ; Fills in the return information for error conditions.
  915. ; Returns the proper return value for OpenFile
  916. ;
  917. ;----------------------------------------------------------------------------
  918. cProc ErrorReturn, <NEAR,PUBLIC>,<si,di,ds>
  919. parmD lpOFStruct ;OFSTRUCT given to OpenFile
  920. parmD lpPath ;Path returned, even when invalid
  921. parmD lpError ;Text for error box
  922. parmW wFlags ;OpenFile flags
  923. parmW wErrCode ;Error code already computed
  924. cBegin
  925. UnSetKernelDS
  926. cmp wErrCode,0 ;Parse error?
  927. jnz @F ;No
  928. mov wErrCode,2 ;Mimic "File not found" error
  929. jmp SHORT ER_ReturnError ;Never prompt on parse error
  930. @@: test BYTE PTR wFlags[1],fPrompt ;Should we do the dialog?
  931. jz ER_ReturnError ;No, return error code
  932. call AreBooting ;if we're still booting, don't prompt
  933. jz ER_ReturnError
  934. lds di,lpError
  935. cmp BYTE PTR ds:[di],0 ;Don't prompt with NULL string.
  936. je ER_ReturnError
  937. cCall Prompt, <ds,di> ;Prompt with error string.
  938. ER_ReturnError:
  939. SetKernelDS
  940. les si,lpOFStruct ;Point to structure again
  941. mov ax,wErrCode ;Get the error code
  942. mov es:[si].opXtra,ax ;In OFSTRUCT, this is the error code
  943. lea di,[si].opFile ;Point to dest string
  944. lds si,lpPath ;Point to the path
  945. call strcpyreg
  946. ;ER_Copy:
  947. ; lodsb ;Copy the sz string for PowerPoint
  948. ; stosb
  949. ; or al,al ;Done?
  950. ; jnz ER_Copy ;No
  951. UnSetKernelDS
  952. mov ax,-1
  953. cEnd
  954. ;!!!!!!!!!!!!!! Everything after this is old
  955. ;---------------------------------------------------------------------------
  956. ; AreBooting
  957. ;
  958. ; Check to see if DOS hook available
  959. ;
  960. ;---------------------------------------------------------------------------
  961. AreBooting PROC NEAR
  962. push ds
  963. SetKernelDS
  964. cmp fInt21,0
  965. pop ds
  966. UnSetKernelDS
  967. ret
  968. AreBooting ENDP
  969. ;---------------------------------------------------------------------------
  970. ; FarGetEnv
  971. ;
  972. ; Gets the correct environment, boot time or no
  973. ;
  974. ;---------------------------------------------------------------------------
  975. FarGetEnv PROC FAR
  976. SetKernelDS
  977. mov si,curTDB
  978. or si,si
  979. jz boot_time
  980. mov ds,si
  981. UnSetKernelDS
  982. mov ds,ds:[TDB_PDB]
  983. not_boot_time:
  984. mov ds,ds:[PDB_environ]
  985. xor si,si
  986. ret
  987. boot_time:
  988. ReSetKernelDS
  989. mov ds,TopPDB
  990. UnSetKernelDS
  991. jmps not_boot_time
  992. FarGetEnv ENDP
  993. ;-----------------------------------------------------------------------;
  994. ; SearchPath ;
  995. ; ;
  996. ; Searches the PATH as defined in the environment for the given file. ;
  997. ; ; ;
  998. ; Arguments: ;
  999. ; ParmD pName Pointer to name ;
  1000. ; ParmD pBuffer Pointer to temporary buffer ;
  1001. ; ParmW Attr AX paramter for DOS (Open, etc.) ;
  1002. ; ;
  1003. ; Returns: ;
  1004. ; AX != 0 ;
  1005. ; ;
  1006. ; Error Returns: ;
  1007. ; AX = -1, BX is error code ;
  1008. ; ;
  1009. ; Registers Preserved: ;
  1010. ; DS ;
  1011. ; ;
  1012. ; Registers Destroyed: ;
  1013. ; BX,CX,DX,DI,SI,ES ;
  1014. ; ;
  1015. ; Calls: ;
  1016. ; GetPureName ;
  1017. ; GetFarEnv ;
  1018. ; ;
  1019. ; History: ;
  1020. ; ;
  1021. ; Mon Oct 12, 1987 08:57:48p -by- David N. Weise [davidw] ;
  1022. ; Added this nifty comment block. ;
  1023. ;-----------------------------------------------------------------------;
  1024. cProc SearchPath,<PUBLIC,FAR>
  1025. ParmD pName ; Pointer to name
  1026. ParmD pBuffer ; Pointer to temporary buffer
  1027. ParmW Attr ; AX paramter for DOS (Open, etc.)
  1028. LocalD pPureName ; pointer to stripped name
  1029. cBegin
  1030. les di,pName
  1031. call GetPureName
  1032. mov pPureName.off,di
  1033. mov pPureName.sel,es
  1034. push cs
  1035. call near ptr FarGetEnv
  1036. mov bx, 3 ; preset error to "path not found"
  1037. spth2: cmp byte ptr [si],0 ; no more enviroment
  1038. jz spthNo
  1039. lodsw
  1040. cmp ax,'AP' ; Look for PATH=
  1041. jnz spth3
  1042. lodsw
  1043. cmp ax,'HT'
  1044. jnz spth3
  1045. lodsb
  1046. cmp al,'='
  1047. jz spth4
  1048. spth3: lodsb
  1049. or al,al
  1050. jnz spth3
  1051. jmp spth2
  1052. spth4: les di,pBuffer
  1053. spth5: lodsb
  1054. stosb
  1055. cmp al,";"
  1056. jz spth6
  1057. or al,al
  1058. jnz spth5
  1059. dec si
  1060. spth6: mov al,'\'
  1061. ifdef FE_SB
  1062. push si
  1063. push di
  1064. mov si,word ptr pBuffer ; buffer address
  1065. dec di ; point di to the byte before ';'
  1066. call MyIsDBCSTrailByte ; is it a DBCS trailing byte?
  1067. pop di
  1068. pop si
  1069. jnc spth6a ;yes, overwrite ';' with '\'
  1070. endif
  1071. cmp es:[di-2],al ; path terminated with '\'
  1072. jnz spth6a
  1073. dec di
  1074. spth6a: mov es:[di-1],al
  1075. push ds
  1076. push si
  1077. cCall MyAnsiToOem,<pPureName,es,di>
  1078. ;** Call the OpenCall function to search for the file. It calls
  1079. ;** the extended error function on failure
  1080. les si,pBuffer ;Point to buffer
  1081. mov ax,Attr ;Get the AX word here and flag
  1082. cCall OpenCall, <es,si,-1> ; OpenCall with -1
  1083. mov bx,ax ;Save the error code if any
  1084. pop si
  1085. pop ds
  1086. jnc spthYes
  1087. cmp byte ptr [si],0 ;At end of path?
  1088. jnz spth4
  1089. spthNo: mov ax,-1
  1090. ;** Bug 14960: If the last error code was path not found, the user
  1091. ;** has a bogus directory in their path. Since we were unable
  1092. ;** to find the file, return file not found instead of path not
  1093. ;** found. 2 November 1991 Clark R. Cyr
  1094. cmp bx, 3 ;Path Not Found?
  1095. jne spthYes
  1096. mov bx, 2 ;Make it File Not Found
  1097. spthYes:
  1098. cEnd
  1099. ; MyAnsiToOem
  1100. ; Used to do ANSI to OEM conversions. This function allows routines
  1101. ; here to call freely without worrying if the keyboard driver can
  1102. ; be called with this yet. At boot time, we can't call the
  1103. ; keyboard driver where these functions reside, so no translation
  1104. ; is done.
  1105. cProc MyAnsiToOem, <PUBLIC,NEAR>, <si,di,ds>
  1106. parmD pSrc
  1107. parmD pDst
  1108. cBegin
  1109. SetKernelDS
  1110. cmp pKeyProc.sel,0 ; is there a keyboard yet?
  1111. jnz mao1 ; Yes, so do translation
  1112. lds si, pSrc ; No, so just copy the strings
  1113. UnSetKernelDS
  1114. les di, pDst
  1115. call strcpyreg
  1116. ;mao0:
  1117. ; lodsb
  1118. ; stosb
  1119. ; or al, al
  1120. ; jnz mao0
  1121. jmps mao2
  1122. ; Not booting, we can call the
  1123. mao1: ; translation routine
  1124. ReSetKernelDS
  1125. cCall [pKeyProc],<pSrc,pDst> ; convert string from AnsiToOem
  1126. mao2:
  1127. cEnd
  1128. ; MyOemToAnsi
  1129. ; Matching function for MyAnsiToOem. See comments above
  1130. cProc MyOemToAnsi,<PUBLIC,NEAR>,<si,di,ds>
  1131. parmD pSrc
  1132. parmD pDst
  1133. cBegin
  1134. SetKernelDS
  1135. cmp pKeyProc.sel,0 ; is there a keyboard yet?
  1136. jnz moa1 ; Yes, do normal conversion
  1137. lds si, pSrc ; No, so just copy the string
  1138. UnSetKernelDS
  1139. les di, pDst
  1140. call strcpyreg
  1141. ;moa0:
  1142. ; lodsb
  1143. ; stosb
  1144. ; or al, al
  1145. ; jnz moa0
  1146. jmps moa2
  1147. moa1: ; Call the translation routine
  1148. ReSetKernelDS
  1149. cCall [pKeyProc1],<pSrc,pDst> ; convert string from AnsiToOem
  1150. moa2:
  1151. cEnd
  1152. ;---------------------------------------------------------------------
  1153. ;
  1154. ; Is Drive number in DI a floppy? A=0, etc. ZF = yes, it is a floppy
  1155. ;
  1156. public IsFloppy
  1157. IsFloppy:
  1158. ifdef WOW
  1159. push dx
  1160. cCall GetDriveType,<di>
  1161. pop dx
  1162. else
  1163. mov bx,1 ; 1 = Get Drive Info from InquireSystem
  1164. push es
  1165. push ds
  1166. SetKernelDS
  1167. cCall [pSysProc],<bx,di>
  1168. pop ds
  1169. UnSetKernelDS
  1170. pop es
  1171. endif
  1172. cmp al,2 ; 2 = removable media
  1173. ret
  1174. FarIsFloppy PROC FAR
  1175. call IsFloppy
  1176. ret
  1177. FarIsFloppy ENDP
  1178. ;----------------------------------------------------------------------------
  1179. ; Prompt
  1180. ;
  1181. ; Puts up the system error box telling the user the file can't be found
  1182. ;
  1183. ;----------------------------------------------------------------------------
  1184. cProc Prompt, <NEAR,PUBLIC>, <si,di,ds>
  1185. parmD lpstr
  1186. cBegin
  1187. SetKernelDS
  1188. mov ax,3 ;Assume CANCEL
  1189. cmp pSErrProc.sel,0 ;Is there a USER yet?
  1190. jz P_End ;No
  1191. ;** Format the string <szCannotFind1><lpstr><szCannotFind2>
  1192. push ds
  1193. pop es
  1194. mov di, dataOffset OutBuf ; ES:DI points to dest
  1195. mov si, dataOffset szCannotFind1
  1196. call strcpyreg
  1197. lds si, [lpstr]
  1198. mov al, byte ptr ds:[si]
  1199. UnSetKernelDS
  1200. mov es:[LastDriveSwapped], al
  1201. call strcpyreg
  1202. push es
  1203. pop ds
  1204. ReSetKernelDS
  1205. mov si, dataOffset szCannotFind2
  1206. call strcpyreg
  1207. ;** Prepare the dialog box
  1208. push ds ;In our DS
  1209. push dataOFFSET OutBuf ;Point to "Cannot find" string
  1210. push ds
  1211. push dataOffset szDiskCap ;Caption
  1212. push 0 ;No left button
  1213. push SEB_CLOSE + SEB_DEFBUTTON ;Button 1 style
  1214. push 0 ;No right button
  1215. call [pSErrProc] ;Put up the system error message
  1216. P_End:
  1217. xor ax,ax
  1218. cEnd
  1219. ;----------------------------------------------------------------------------
  1220. ; StartString
  1221. ;
  1222. ; Prepares the start of the string for the sys error box
  1223. ;
  1224. ; ES:BX is the pointer to the full pathname
  1225. ; DS:DX is the string "Can't find file X:"
  1226. ;
  1227. ;----------------------------------------------------------------------------
  1228. cProc strcpyreg, <NEAR,PUBLIC>
  1229. cBegin nogen
  1230. cld
  1231. @@: lodsb ; copy from DS:SI
  1232. stosb ; to ES:DI
  1233. or al, al
  1234. jnz @B ; including 0
  1235. dec di ; point to trailing 0
  1236. ret
  1237. cEnd nogen
  1238. ;cProc StartString, <NEAR,PUBLIC>
  1239. ;cBegin NOGEN
  1240. ; CheckKernelDS
  1241. ; ReSetKernelDS
  1242. ;
  1243. ; ;** Copy the first part of the string
  1244. ; cld
  1245. ; push es ;Save the parameter
  1246. ; push bx
  1247. ; mov dx,dataOffset szCannotFind1 ;Point to Can't Find string
  1248. ; call AppendFirst ;Put in OutBuf
  1249. ; pop bx
  1250. ; pop es
  1251. ;
  1252. ; ;** Save the drive letter for compatibility with ancient disk swaps
  1253. ; mov al,es:[bx] ;Get drive letter
  1254. ; mov [LastDriveSwapped],al ;Save it for GetLastDiskChange
  1255. ;
  1256. ; ;** Append the filename portion
  1257. ; smov ds,es
  1258. ; mov dx,bx
  1259. ; jmps Append
  1260. ;
  1261. ;cEnd NOGEN
  1262. ; AppendFirst & Append
  1263. ; Append ASCIIZ string to the static string OutBuf
  1264. ;
  1265. ; ENTRY: DS:DX points to a string to append to the static buffer
  1266. ;
  1267. ; AppendFirst clears the static string and appends the new string
  1268. ; as the first part of the string.
  1269. ; Append just appends the new string on the end of the current string.
  1270. cProc AppendFirst, <PUBLIC,NEAR>
  1271. cBegin NOGEN
  1272. CheckKernelDS
  1273. ReSetKernelDS
  1274. mov [BufPos],dataOffset OutBuf
  1275. UnSetKernelDS
  1276. ;Append:
  1277. push si ;Save some registers
  1278. push di
  1279. SetKernelDS es
  1280. mov di,[BufPos]
  1281. mov si,dx
  1282. call strcpyreg
  1283. ;ap1: lodsb
  1284. ; stosb
  1285. ; or al,al
  1286. ; jnz ap1
  1287. dec di
  1288. mov [BufPos],di
  1289. pop di
  1290. pop si
  1291. ret
  1292. cEnd NOGEN
  1293. UnSetKernelDS es
  1294. ; GetPureName
  1295. ; Strips the drive and directory portions of a pathname off.
  1296. ; ENTRY: ES:DI points to pathname
  1297. ; EXIT: ES:DI points to "pure" name in same string
  1298. cProc GetPureName, <NEAR,PUBLIC>
  1299. cBegin
  1300. ;** Do FE_SB version:
  1301. ;* It is not possible to search filename delimiter by backward
  1302. ;** search in case of FE_SB version, so we use forward search.
  1303. IFDEF FE_SB
  1304. mov bx,di
  1305. iup0:
  1306. mov al,es:[di]
  1307. test al,al ; end of string?
  1308. jz iup2 ; jump if so
  1309. inc di
  1310. cmp al,'\'
  1311. jz iup1
  1312. cmp al,'/'
  1313. jz iup1
  1314. cmp al,':'
  1315. jz iup1
  1316. call MyIsDBCSLeadByte ; see if char is DBC
  1317. jc iup0 ; jump if not a DBC
  1318. inc di ; skip to detemine 2nd byte of DBC
  1319. jmp iup0
  1320. iup1:
  1321. mov bx,di ; update purename candidate
  1322. jmp iup0
  1323. iup2:
  1324. mov di,bx ; di points purename pointer
  1325. ;** Do normal version:
  1326. ;** Here we can just back up until we find the proper char
  1327. ELSE
  1328. cld
  1329. xor al,al
  1330. mov cx,-1
  1331. mov bx,di
  1332. repne scasb
  1333. inc cx
  1334. inc cx
  1335. neg cx
  1336. iup0: cmp bx,di ; back to beginning of string?
  1337. jz iup1 ; yes, di points to name
  1338. mov al,es:[di-1] ; get next char
  1339. cmp al,'\' ; next char a '\'?
  1340. jz iup1 ; yes, di points to name
  1341. cmp al,'/' ; next char a '/'
  1342. jz iup1
  1343. cmp al,':' ; next char a ':'
  1344. jz iup1 ; yes, di points to name
  1345. dec di ; back up one
  1346. jmp iup0
  1347. iup1:
  1348. ENDIF
  1349. cEnd
  1350. ; ParseFile
  1351. ;
  1352. ; ENTRY: DS:SI points to unqualified pathname
  1353. ; ES:DI points to buffer to be used for qualified name
  1354. ; EXIT: Buffer previously pointed to by ES:DI now has full
  1355. ; unambiguous pathname
  1356. ; DX is length of path portion of entered pathname
  1357. ; AX is total length of pathname
  1358. ; DI is number of slashes
  1359. ; CX is length of path ON ERROR ONLY!!! (for PowerPoint)
  1360. LONG_UNC_NAMES equ 1
  1361. cProc ParseFile, <NEAR,PUBLIC>
  1362. localW cSlash ;Word ptr [bp][-2]
  1363. localW cchPath ;Word ptr [bp][-4]
  1364. localW fUNC ;Flag for UNC name (\\foo\bar)
  1365. if LONG_UNC_NAMES
  1366. localW fCountUNC ;Indicates we are parsing UNC name
  1367. else
  1368. localW fFirstUNC ;Indicates we are parsing UNC name
  1369. endif
  1370. cBegin
  1371. mov cSlash,0 ;Zero the local variables
  1372. mov cchPath,0
  1373. mov fUNC,0 ;Assume it's not UNC
  1374. cld
  1375. ;** If a drive is on the path, parse it. Otherwise, get the current
  1376. ;** drive.
  1377. cmp byte ptr ds:[si+1],':'
  1378. jne nodrive
  1379. lodsb
  1380. inc si
  1381. or al,20h ; convert to lower case
  1382. sub al,'a' ; convert to number
  1383. jb @F ;Not valid, so return error
  1384. cmp al,'z'-'a'
  1385. jbe gotdrive
  1386. @@: jmp gpFail2
  1387. nodrive:
  1388. mov ah,19h
  1389. DOSCALL
  1390. gotdrive:
  1391. mov dl,al
  1392. inc dl
  1393. add al,'A' ; convert to ascii
  1394. mov ah,':'
  1395. ;** If this is a UNC name, we don't want to copy the drive letter
  1396. ;** as it is legal but unnecessary for a full path
  1397. mov fUNC, 1
  1398. if LONG_UNC_NAMES
  1399. mov fCountUNC, 2
  1400. else
  1401. mov fFirstUNC, 1
  1402. endif
  1403. cmp WORD PTR ds:[si], '\\' ;Is this a UNC? (\\foo\bar)
  1404. je PF_DriveOK ;Yes, don't insert drive
  1405. cmp WORD PTR ds:[si], '//' ;Is this a UNC? (//foo/bar)
  1406. je PF_DriveOK ;Yes, don't insert drive
  1407. mov fUNC, 0 ;Nope, not UNC
  1408. if LONG_UNC_NAMES
  1409. mov fCountUNC, 0
  1410. else
  1411. mov fFirstUNC, 0
  1412. endif
  1413. stosw ;Write drive letter and colon
  1414. add cchPath,2 ;Add two chars to path len
  1415. PF_DriveOK:
  1416. push di ; Save beginning of path
  1417. ;** If we start with a slash, we have a qualified path here
  1418. ;* so we don't have to search to find the current path.
  1419. ;** Otherwise, we have to find where we are and make the path.
  1420. mov bx,'/' shl 8 + '\' ;Separator characters
  1421. mov al,ds:[si] ;Get first character
  1422. cmp al,bh ;If it's either one, we have a
  1423. je getpath0 ; full path, so don't search
  1424. cmp al,bl
  1425. je getpath0
  1426. mov al,bl ;Get a '\'
  1427. stosb ; and put in the buffer
  1428. inc cchPath ;Bump path count
  1429. mov cx,ds ;Prepare for DOS call: Save DS
  1430. xchg si,di ;DS:SI needs to point to buffer
  1431. mov ax,es
  1432. mov ds,ax
  1433. mov ah,47h ;DOS #47: Get Current Directory
  1434. DOSCALL
  1435. jnc @F
  1436. jmp gpfail
  1437. @@:
  1438. push cx ;DOS returns OEM characters
  1439. push bx ; so convert to ANSI
  1440. cCall MyOemToAnsi,<ds,si,ds,si>
  1441. pop bx
  1442. pop ds
  1443. xchg si,di ;Get pointer back
  1444. xor al,al
  1445. mov cx,-1
  1446. repnz scasb ;Find the end of the string
  1447. neg cx
  1448. dec cx ;Don't count the terminator
  1449. dec cx
  1450. add cchPath,cx ;Add into path count
  1451. dec di ;Don't leave DI past the zero byte
  1452. ifdef FE_SB ;Check for trailing slash, DBCS-style
  1453. push si
  1454. push di
  1455. mov si,di
  1456. sub si,cx ;es:si->string address
  1457. dec di ;es:di->last byte
  1458. call MyIsDBCSTrailByte ;is the last byte a DBCS trailing byte?
  1459. pop di
  1460. pop si
  1461. jnc loopGD3 ;yes, append a '\'
  1462. ;no, fall through
  1463. endif
  1464. mov al,es:[di-1] ;Check for trailing slash. Non-DBCS
  1465. cmp al,bh ;If there is one, we're done here
  1466. je getpath0
  1467. cmp al,bl
  1468. je getpath0
  1469. IFDEF FE_SB
  1470. loopGD3:
  1471. ENDIF
  1472. mov al,bl ;Put a trailing slash on
  1473. stosb
  1474. inc cchPath
  1475. ;** Parse the pathname the user gave us
  1476. getpath0:
  1477. PF_GetPath label NEAR
  1478. public PF_GetPath
  1479. xor cx,cx ;CL=# of chars, CH=# of '.'
  1480. mov dx,di ;DX points to start of user chars
  1481. gp0:
  1482. lodsb ;Get a character
  1483. cmp al,bl ;Slash?
  1484. je gp1 ;Yes
  1485. cmp al,bh
  1486. ifdef FE_SB
  1487. je gp1 ;Too far if DBCS enable....
  1488. jmp gp2
  1489. else
  1490. jne gp2 ;No, skip this
  1491. endif
  1492. gp1: ;Character is a slash
  1493. ;** If we have a UNC name, two slashes are OK
  1494. ;** (just at the start of the filename)
  1495. cmp cchPath, 0 ;Start of path?
  1496. jne PF_NotUNC ;No, even if UNC, not valid here
  1497. cmp fUNC, 0 ;UNC pathname?
  1498. je PF_NotUNC ;No, handle normally
  1499. stosb ;Store the first slash
  1500. lodsb ;Get the second slash
  1501. inc cchPath ;Another character in string
  1502. jmp SHORT gp1f ;Skip double slash failure
  1503. PF_NotUNC:
  1504. cmp ds:[si],bl ; if double slash, bad file name
  1505. jz gp1SkipSlash ; so we skip the extra slashes
  1506. cmp ds:[si],bh ; to be compatible with win32
  1507. jnz gp1DoneSlash ; MonkeyIsland bug 220764
  1508. gp1SkipSlash:
  1509. inc si
  1510. jmp SHORT PF_NotUNC ; check for more slashes
  1511. gp1DoneSlash:
  1512. if LONG_UNC_NAMES
  1513. dec fCountUNC ; Move to next portion of path
  1514. jns @f
  1515. mov fCountUNC,0
  1516. @@:
  1517. else
  1518. ;** When we get here, we will be on the first slash AFTER the
  1519. ;** UNC slashes: (\\foo\bar) (or any succeeding slash)
  1520. ;** ^
  1521. ;** So, we want clear the fFirstUNC flag so we don't allow
  1522. ;** more than 8 characters before a dot.
  1523. mov fFirstUNC, 0
  1524. endif
  1525. gp1f:
  1526. inc cSlash ; we found a slash
  1527. cmp cl,ch ; number of chars = number of '.'
  1528. jne gp1b ; nope....
  1529. or cx,cx
  1530. jnz gp001
  1531. ifdef FE_SB
  1532. jmp gp2b ; We need 16 bits branch
  1533. else
  1534. jmp SHORT gp2b
  1535. endif
  1536. gp001:
  1537. cmp cl,2 ; if more than 2 '.'
  1538. ja gpFail ; then we are bogus
  1539. dec di
  1540. ifdef FE_SB
  1541. dec cchPath ; adjust path string length
  1542. endif
  1543. dec cl
  1544. jz getpath0
  1545. ifdef FE_SB
  1546. dec di
  1547. dec di
  1548. mov dx, di
  1549. sub di, cchPath
  1550. add di, 4
  1551. cmp di, dx
  1552. jnc gpfail ; illegal path such as "c:.." or "c:\.."
  1553. mov cchPath, 3
  1554. gp1a:
  1555. xor cx, cx
  1556. gp1bb:
  1557. inc di
  1558. inc cx
  1559. mov al, es:[di]
  1560. cmp al, bl
  1561. jz gp1c
  1562. call MyIsDBCSLeadByte
  1563. jc gp1bb
  1564. inc di
  1565. inc cx
  1566. jmp gp1bb
  1567. gp1c:
  1568. cmp di, dx
  1569. jz gp1d
  1570. add cchPath, cx
  1571. jmp gp1a
  1572. gp1d:
  1573. sub di, cx
  1574. inc di ; new di points previous '\'+1
  1575. jmp getpath0
  1576. else
  1577. mov di,dx
  1578. gp1a:
  1579. dec di
  1580. mov al,es:[di-1]
  1581. cmp al,bl
  1582. je getpath0
  1583. cmp al,':'
  1584. jne gp1a
  1585. endif
  1586. gpfail:
  1587. pop ax
  1588. gpFail2:
  1589. xor ax,ax
  1590. jmp gpexit
  1591. gp1b:
  1592. mov al,bl
  1593. stosb
  1594. inc cchPath
  1595. jmp getpath0
  1596. gp2:
  1597. or al,al
  1598. jnz gp002
  1599. ifdef FE_SB
  1600. jmp gpx
  1601. else ; !FE_SB
  1602. jmp short gpx
  1603. endif ; !FE_SB
  1604. gp002:
  1605. cmp al,' '
  1606. jb gpFail
  1607. ja gp20
  1608. gp2x: lodsb ; if space encountered continue scanning...
  1609. or al,al ; if end of string, all ok
  1610. ifdef FE_SB
  1611. jnz gp2x_01
  1612. jmp gpx
  1613. gp2x_01:
  1614. else
  1615. jz gpx
  1616. endif
  1617. cmp al,' ' ; if space, keep looking...
  1618. jz gp2x
  1619. jmps gpFail ; otherwise error
  1620. gp20: cmp al,';'
  1621. jz gpFail
  1622. cmp al,':'
  1623. jz gpFail
  1624. cmp al,','
  1625. jz gpFail
  1626. cmp al,'|'
  1627. jz gpFail
  1628. cmp al,'+'
  1629. jz gpFail
  1630. cmp al,'<'
  1631. jz gpFail
  1632. cmp al,'>'
  1633. jz gpFail
  1634. cmp al,'"'
  1635. jz gpFail
  1636. cmp al,'['
  1637. jz gpFail
  1638. cmp al,']'
  1639. jz gpFail
  1640. cmp al,'='
  1641. jz gpFail
  1642. inc cl ; one more char
  1643. ifdef FE_SB
  1644. call MyIsDBCSLeadByte ; First byte of 2 byte character?
  1645. jc gp2a ; No, convert to upper case
  1646. stosb ; Yes, copy 1st byte
  1647. inc cchPath
  1648. lodsb ; Fetch second byte
  1649. inc cl
  1650. jmps gp2a1 ; with no case conversion
  1651. gp2a:
  1652. endif
  1653. call MyUpper
  1654. gp2a1:
  1655. cmp cchPath,127 ; DOS pathmax is 128, room for null.
  1656. ja gpFail
  1657. gp2b:
  1658. stosb
  1659. inc cchPath
  1660. cmp al,'.'
  1661. jne gp2c
  1662. inc ch
  1663. mov ah,cl
  1664. dec ah
  1665. gp2c:
  1666. if LONG_UNC_NAMES
  1667. ;** If this is a UNC name, don't bother checking lengths
  1668. cmp fCountUNC,0 ; Past \\foo\bar yet?
  1669. je PF_NotUNCPart
  1670. else
  1671. cmp fFirstUNC, 0 ;First UNC name?
  1672. je PF_NotFirstUNC ;Nope
  1673. or ch,ch ;'.' encountered yet?
  1674. jnz PF_NotFirstUNC ;Yes, treat like normal name
  1675. cmp cl, 11 ;11 chars allowed with no '.'
  1676. ja gpFv ;Too many
  1677. endif
  1678. jmp gp0 ;Ok
  1679. if LONG_UNC_NAMES
  1680. PF_NotUNCPart:
  1681. else
  1682. PF_NotFirstUNC:
  1683. endif
  1684. ;** Check other lengths
  1685. cmp ch,0 ; did we find a . yet?
  1686. jz gpT1 ; no, max count is 8
  1687. cmp cl,12 ; otherwise check for 12 chars
  1688. ja gpFv ; if more, no good
  1689. mov al,cl
  1690. sub al,ah
  1691. cmp al,3+1 ; more than 3 chars in extension?
  1692. ja gpFv
  1693. jmp gp0 ; continue
  1694. gpT1: cmp cl,8 ; did we find 8 chars between / and .
  1695. ja gpFv ; if more, we fail
  1696. jmp gp0
  1697. gpx:
  1698. ;** UNC names are invalid if they are SHORTER than the following:
  1699. ;** \\server\share\f
  1700. cmp fUNC,0 ;UNC name?
  1701. jz PF_EnoughSlashes ;No
  1702. cmp cSlash,3 ;We count \\ as one slash
  1703. jb gpFv ;Not enough, so fail it
  1704. PF_EnoughSlashes:
  1705. cmp ch,1
  1706. je gpx1
  1707. ja gpFv ; if more than 1 we fail
  1708. mov ah,cl ; No extension given
  1709. gpx1:
  1710. mov es:[di],al ; Zero terminate destination
  1711. xchg al,ah ; Get length of name in CX
  1712. or ax,ax
  1713. jnz gpx2
  1714. gpFv: jmp gpFail
  1715. gpx2:
  1716. cmp ax,8 ; but no more than 8
  1717. ja gpFv
  1718. pop ax
  1719. sub dx,ax ;Get length of path in DX
  1720. inc dx ;Add drive letter and :, less one
  1721. ;** Never a drive letter or colon for the UNC name case
  1722. cmp fUNC,0 ;UNC name?
  1723. jz @F ;Yes, don't do this
  1724. dec dx ;UNC names ALWAYS have >=3 slashes
  1725. dec dx
  1726. @@: mov ax,dx ;AX = length of entire path
  1727. xor ch,ch ;Clear high byte for 16 bit add
  1728. add ax,cx
  1729. cmp dx,1 ;If length is one, we have C:\ case
  1730. jne @F ;Nope
  1731. inc dx ;Bump it
  1732. @@:
  1733. gpexit:
  1734. mov di,cSlash ;DI retured as cSlash
  1735. cEnd
  1736. ;---------------------------------------------------------------
  1737. ;
  1738. ; Return the drive letter of last drive a disk was swapped in
  1739. ;
  1740. cProc GetLastDiskChange, <PUBLIC,FAR>
  1741. cBegin nogen
  1742. xor ax,ax
  1743. push ds
  1744. SetKernelDS
  1745. xchg al,[LastDriveSwapped]
  1746. pop ds
  1747. UnSetKernelDS
  1748. ret
  1749. cEnd nogen
  1750. assumes ds,nothing
  1751. assumes es,nothing
  1752. cProc MyOpenFile,<PUBLIC,FAR>,<si,di>
  1753. ParmD srcFile
  1754. ParmD dstFile
  1755. ParmW Command
  1756. cBegin
  1757. SetKernelDS
  1758. xor ax,ax
  1759. cmp [wMyOpenFileReent], ax ; Prevent reentering this procedure
  1760. jne myoffail
  1761. ifdef WOW
  1762. and Command, NOT OF_VERIFY ; Don't Bother with verify for internal
  1763. ; It slows us down
  1764. endif
  1765. mov es,[CurTDB]
  1766. mov ax,es:[TDB_ErrMode] ; Enable INT 24h processing
  1767. and es:[TDB_ErrMode],NOT 1
  1768. mov [myofint24],ax ; Save old INT 24h flag
  1769. mov [wMyOpenFileReent],1
  1770. cCall IOpenFile,<srcFile,dstFile,Command>
  1771. mov es,[CurTDB] ; Restore old INT 24h processing flag
  1772. mov dx,[myofint24]
  1773. mov es:[TDB_ErrMode],dx
  1774. mov [wMyOpenFileReent],0
  1775. jmps mof_ret
  1776. myoffail:
  1777. krDebugOut DEB_ERROR, "MyOpenFile not reentrant"
  1778. dec ax
  1779. mof_ret:
  1780. UnSetKernelDS
  1781. cEnd
  1782. sEnd CODE
  1783. sBegin MISCCODE
  1784. assumes CS,MISCCODE
  1785. assumes ds,nothing
  1786. assumes es,nothing
  1787. externNP MISCMapDStoDATA
  1788. externFP GetWindowsDirectory
  1789. cProc DeletePathname,<PUBLIC,FAR>
  1790. ; ParmD path
  1791. cBegin nogen
  1792. pop bx
  1793. pop cx
  1794. mov ax,4100h ; dos delete file function
  1795. push ax
  1796. push cx
  1797. push bx
  1798. errn$ OpenPathname
  1799. cEnd nogen
  1800. cProc OpenPathname,<PUBLIC,FAR>,<ds,si,di>
  1801. ParmD path
  1802. ParmW attr
  1803. LocalV Buffer,MaxFileLen
  1804. cBegin
  1805. mov ax,attr ; get attribute
  1806. or ah,ah ; function code already set...
  1807. jnz opn0 ; ...yes, otherwise...
  1808. mov ah,3dh ; ...default to open
  1809. opn0: mov di,ax
  1810. ; We don't use open test for existance, rather we use get
  1811. ; file attributes. This is because if we are using Novell
  1812. ; netware, opening a file causes Novell to execute its
  1813. ; own path searching logic, but we want our code to do it.
  1814. call MISCMapDStoDATA
  1815. ReSetKernelDS
  1816. cmp fNovell, 0
  1817. lds dx,path ; get pointer to pathname
  1818. UnSetKernelDS
  1819. je opnNoNovell
  1820. mov ax,4300h ; Get file attributes
  1821. DOSFCALL ; Does the file exist?
  1822. jc opnnov ; No, then dont do the operation
  1823. opnNoNovell:
  1824. mov ax,di ; Yes, restore operation to AX
  1825. DOSFCALL
  1826. jnc opn2
  1827. opnnov:
  1828. lea ax,Buffer
  1829. regptr dsdx,ds,dx
  1830. regptr ssax,ss,ax
  1831. cCall SearchPath,<dsdx,ssax,di>
  1832. opn2: mov bx,ax
  1833. cEnd
  1834. ;---------------------------------------------------------------
  1835. ;
  1836. ; Return the drive letter of a good disk to put a temp file on
  1837. ;
  1838. ;
  1839. cProc GetTempDrive,<PUBLIC,FAR>
  1840. ; ParmB Drive
  1841. cBegin nogen
  1842. mov bx,sp
  1843. push si
  1844. push di
  1845. mov ax,ss:[bx+4]
  1846. and al,not TF_FORCEDRIVE
  1847. jnz gtd1
  1848. mov ah,19h ; get the current disk
  1849. DOSFCALL
  1850. add al,'A'
  1851. gtd1: and al,01011111b ; convert to upper case (always a-z)
  1852. test byte ptr ss:[bx+4],TF_FORCEDRIVE ; Forcing drive letter?
  1853. jnz gtdz ; Yes, all done
  1854. sub al,'A' ; A: = 0, etc.
  1855. cbw
  1856. mov si,ax ; SI = drive to return if no hard disk
  1857. xor di,di ; start with drive A
  1858. gtd2: call FarIsFloppy ; while drive = floppy, keep looking
  1859. cmp al,3 ; did we find a hard disk?
  1860. mov dx,1 ; return we have a hard disk
  1861. jz gtdx ; yes, return it
  1862. inc di
  1863. cmp di,"Z"-"A"
  1864. jbe gtd2
  1865. xor dx,dx ; indicate its a floppy
  1866. mov di,si ; return default disk
  1867. gtdx: mov ax,di
  1868. add al,"A"
  1869. gtdz: mov ah,":"
  1870. pop di
  1871. pop si
  1872. ret 2
  1873. cEnd nogen
  1874. cProc hextoa,<PUBLIC,NEAR>
  1875. cBegin nogen
  1876. mov ah,al
  1877. mov cl,4
  1878. shr al,cl
  1879. and ah,0Fh
  1880. add ax,3030h
  1881. cmp al,39h
  1882. jbe hextoa1
  1883. add al,7
  1884. hextoa1:
  1885. cmp ah,39h
  1886. jbe hextoa2
  1887. add ah,7
  1888. hextoa2:
  1889. ret
  1890. cEnd nogen
  1891. ;---------------------------------------------------------------
  1892. ;
  1893. cProc IGetTempFileName,<PUBLIC,FAR>,<si,di>
  1894. parmW drive
  1895. parmD lpPrefix
  1896. parmW nUnique
  1897. parmD lpBuf
  1898. localW myUnique
  1899. localW mydx
  1900. localW mybuf
  1901. cBegin
  1902. sub sp, 128 ; local buffer for buiding lpBuf
  1903. mov di, sp
  1904. mov mybuf, sp ; save
  1905. cCall GetTempDrive,<drive>
  1906. mov mydx,dx
  1907. ;les di,lpBuf
  1908. smov es, ss
  1909. stosw ; AX = 'drive:'
  1910. mov ax,drive
  1911. test al,TF_FORCEDRIVE
  1912. jnz stmpForce
  1913. call FarGetEnv ; look for environ TEMP=
  1914. stmp2:
  1915. lodsw
  1916. or al,al ; no more enviroment
  1917. jz stmpNo
  1918. cmp ax,'ET' ; Look for TEMP=
  1919. jne stmp3
  1920. lodsw
  1921. cmp ax,'PM'
  1922. jne stmp3
  1923. lodsb
  1924. cmp al,'='
  1925. je stmpYes
  1926. stmp3: lodsb ; find end of string
  1927. or al,al
  1928. jnz stmp3
  1929. jmp stmp2
  1930. stmpYes:
  1931. ifdef FE_SB
  1932. mov al,[si]
  1933. mov ah,0
  1934. call FarMyIsDBCSLeadByte
  1935. jnc stmpnodrive
  1936. endif
  1937. cmp byte ptr [si+1],':' ; TEMP has drive?
  1938. jne stmpnodrive
  1939. dec di
  1940. dec di
  1941. stmpnodrive: ; copy path to ES:DI
  1942. lodsb
  1943. or al,al
  1944. jz stmpPath
  1945. stosb
  1946. jmp stmpnodrive
  1947. stmpForce:
  1948. mov al,'~'
  1949. stosb
  1950. jmps stmpNo1
  1951. stmpNo: ; ES:DI points to "drive:"
  1952. dec di
  1953. dec di
  1954. cCall GetWindowsDirectory, <esdi, 144>
  1955. add di, ax
  1956. stmpPath: ; ES:DI points to "drive:path"
  1957. mov ax,'~\'
  1958. cmp es:[di-1],al ; does it already end in \
  1959. jnz stmpNoF ; no, just store it
  1960. dec di ; override it
  1961. stmpNoF:
  1962. stosw
  1963. stmpNo1:
  1964. lds si,lpPrefix
  1965. mov cx,3
  1966. stmpPfx:
  1967. lodsb
  1968. or al,al
  1969. jz stmpPfx1
  1970. stosb
  1971. loop stmpPfx
  1972. stmpPfx1:
  1973. mov dx,nUnique
  1974. or dx,dx
  1975. jnz stmpNum
  1976. mov ah,2Ch
  1977. DOSFCALL
  1978. xor dx,cx
  1979. stmpNum:
  1980. mov myUnique,dx
  1981. jnz stmpNum1
  1982. inc dx ; Dont ever use 0 as the unique num.
  1983. jmp stmpNum
  1984. stmpNum1:
  1985. mov al,dh
  1986. call hextoa
  1987. stosw
  1988. mov al,dl
  1989. call hextoa
  1990. stosw
  1991. mov ax,'T.'
  1992. stosw
  1993. mov ax,'PM'
  1994. stosw
  1995. xor ax,ax
  1996. stosb
  1997. ; Don't call AnsiUpper on this string because it has OEM characters
  1998. ; in it (from the app and the temp environment variable).
  1999. cmp nUnique,0
  2000. jne stmpDone
  2001. ;lds dx,lpBuf
  2002. mov dx, mybuf
  2003. smov ds, ss
  2004. mov ax,5B00h
  2005. xor cx,cx
  2006. DOSFCALL
  2007. jnc stmpClose
  2008. cmp al,80 ; Did we fail because the file
  2009. jnz stmpfail ; already exists?
  2010. sub di,9
  2011. mov dx,myUnique
  2012. inc dx
  2013. jmp stmpNum
  2014. stmpClose:
  2015. mov bx,ax
  2016. mov ah,3Eh
  2017. DOSFCALL
  2018. jmps stmpdone
  2019. stmpfail:
  2020. xor ax,ax
  2021. mov myunique,ax
  2022. stmpdone:
  2023. mov di, mybuf ; robustness crap
  2024. smov es, ss ; bug #15493 ami pro
  2025. RegPtr esdi, es, di
  2026. cCall lstrcpy <lpBuf,esdi> ; now copy to user spc
  2027. mov ax,myunique
  2028. mov dx,mydx
  2029. add sp, 128
  2030. cEnd
  2031. ;-----------------------------------------------------------------------;
  2032. ; GetDriveType
  2033. ;
  2034. ; Entry:
  2035. ; parmW drive Disk Drive Information (Drive A = 0)
  2036. ;
  2037. ; Returns:
  2038. ; ax = 0 means the drive does not exist. if dx != 0 then the drive
  2039. ; maps to the drive in dx instead (A = 1) AND the drive is
  2040. ; REMOVEABLE.
  2041. ; ax = 1 means the drive does not exist. if dx != 0 then the drive
  2042. ; maps to the drive in dx instead (A = 1) AND the drive is
  2043. ; FIXED.
  2044. ; ax = 2 means the drive is removable media
  2045. ; ax = 3 means the drive is fixed media
  2046. ; ax = 4 means the drive is fixed media and remote
  2047. ;
  2048. ; Registers Destroyed:
  2049. ;
  2050. ; History:
  2051. ; Mon 16-Oct-1989 21:14:27 -by- David N. Weise [davidw]
  2052. ; Wrote it!
  2053. ;-----------------------------------------------------------------------;
  2054. assumes ds,nothing
  2055. assumes es,nothing
  2056. ifndef WOW - We thunk this API its too slow
  2057. cProc GetDriveType,<PUBLIC,FAR>
  2058. ; parmW drive
  2059. cBegin nogen
  2060. mov bx,sp
  2061. push ds
  2062. call MISCMapDStoDATA
  2063. ResetKernelDS
  2064. mov ax,1 ; 1 = Get Drive Info from InquireSystem
  2065. mov bx,ss:[bx+4]
  2066. cCall pSysProc,<ax,bx>
  2067. pop ds
  2068. ret 2
  2069. cEnd nogen
  2070. endif; WOW
  2071. sEnd MISCCODE
  2072. end