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.

683 lines
15 KiB

  1. TITLE LSTRING
  2. include kernel.inc
  3. include gpfix.inc
  4. include wowcmpat.inc
  5. DataBegin
  6. externB fFarEast ; non zero if far eastern keyboard
  7. externB KeyInfo ; Info returned by KEYBOARD.Inquire
  8. ifdef FE_SB
  9. externB fDBCSLeadTable ; DBCS Lead byte flag array
  10. endif
  11. if ROM
  12. externD pStringFunc ; Entry point of string functions in USER.
  13. endif
  14. DataEnd
  15. sBegin CODE
  16. assumes CS,CODE
  17. assumes DS,NOTHING
  18. assumes ES,NOTHING
  19. ifdef WOW
  20. externNP MyGetAppWOWCompatFlags
  21. endif
  22. ife ROM
  23. externD pStringFunc ; Entry point of string functions in USER.
  24. endif
  25. ; Function codes for all the string functions in USER
  26. ;
  27. ANSINEXT_ID equ 1
  28. ANSIPREV_ID equ 2
  29. ANSIUPPER_ID equ 3
  30. ANSILOWER_ID equ 4
  31. ;
  32. ; lstrlen: Same as strlen except for taking long ptrs
  33. ;
  34. cProcVDO lstrlen,<PUBLIC,FAR>
  35. ; parmD pStr
  36. cBegin nogen
  37. mov bx,sp
  38. push di
  39. beg_fault_trap sl_trap
  40. les di,ss:[bx+4]
  41. cld
  42. xor ax,ax ; get zero in ax
  43. mov cx,-1 ; at most 64 k to move
  44. repnz scasb ; look for end
  45. mov ax,cx
  46. neg ax
  47. dec ax
  48. dec ax
  49. end_fault_trap
  50. sl_exit:
  51. pop di
  52. ret 4
  53. cEnd nogen
  54. sl_trap:
  55. fault_fix_stack
  56. xor ax,ax
  57. jmp sl_exit
  58. lstr_trap:
  59. fault_fix_stack
  60. lstrfinish proc far
  61. pop di
  62. pop si
  63. pop ds
  64. ret 8
  65. lstrfinish endp
  66. ; lstrcpyn - lstrcpy with a limit length -- NEVER null-padded, but ALWAYS
  67. ; null-terminated.
  68. cProc lstrcpyn,<PUBLIC,FAR>,<ds,si,di>
  69. parmD pDst
  70. parmD pSrc
  71. parmW wLen
  72. cBegin
  73. xor dx,dx
  74. jmp lstrn
  75. cEnd nogen
  76. ; lstrcatn - lstrcat with a limit length -- NEVER null-padded, but ALWAYS
  77. ; wLen is the pDst buffer size
  78. cProc lstrcatn,<PUBLIC,FAR>,<ds,si,di>
  79. parmD pDst
  80. parmD pSrc
  81. parmW wLen
  82. cBegin
  83. mov dx,1
  84. lstrn:
  85. mov bx, [wLen]
  86. or bx, bx
  87. jz lstrn_err1
  88. beg_fault_trap lstrn_err
  89. cld
  90. les di, [pSrc] ; Find length of source string
  91. mov cx, -1
  92. xor ax, ax
  93. repnz scasb
  94. not cx ; length now in CX (incl null term)
  95. lds si, [pSrc] ; Set up for copy
  96. les di, [pDst]
  97. cmp dx,0 ; check for lstrcatn or lstrcpyn
  98. je lstrn_prepcopy
  99. push cx ; Store source string length
  100. xor ax,ax ; get zero in ax
  101. mov cx,-1 ; at most 64 k to look
  102. repnz scasb ; look for end
  103. not cx
  104. mov ax, cx
  105. pop cx
  106. cmp bx, ax
  107. jle lstrn_finish
  108. dec di ; Point at null byte
  109. dec ax ; remove null terminator
  110. sub bx, ax
  111. lstrn_prepcopy:
  112. cmp cx, bx ; Check destination length
  113. jbe lstrn_copy
  114. mov cx, bx
  115. lstrn_copy:
  116. xor ax,ax ; do we really need this ??
  117. dec cx ; save space for null
  118. shr cx, 1 ; Copy the string
  119. rep movsw
  120. adc cx, cx
  121. rep movsb
  122. stosb ; null terminate string
  123. end_fault_trap
  124. lstrn_finish:
  125. mov ax, [OFF_pDst] ; ptr to dest in DX:AX
  126. mov dx, es
  127. lstrn_exit:
  128. cEnd
  129. lstrn_err:
  130. fault_fix_stack
  131. krDebugOut DEB_ERROR, "GP fault in lstrcatn / lstrcpyn"
  132. lstrn_err1:
  133. xor ax, ax
  134. cwd
  135. jmps lstrn_exit
  136. lstrsetup:
  137. pop dx
  138. mov bx,sp
  139. push ds
  140. push si
  141. push di
  142. beg_fault_trap lstr_trap
  143. lds si,ss:[bx+4]
  144. les di,ss:[bx+8]
  145. cld
  146. jmp dx
  147. ;
  148. ;lstrcpy: strcpy with long pointers
  149. ;
  150. cProcVDO lstrcpy,<PUBLIC,FAR>
  151. ; parmD pDst ; [bx+8]
  152. ; parmD pSrc ; [bx+4]
  153. cBegin nogen
  154. call lstrsetup
  155. mov dx,di ; save for return
  156. lcp1: lodsb
  157. stosb
  158. or al,al
  159. jnz lcp1
  160. xchg ax,dx ; return ds:ax = original dest
  161. mov dx,es
  162. jmp lstrfinish
  163. cEnd nogen
  164. ;
  165. ;lstrcat: Same as strcat except with long ptrs.
  166. ;
  167. cProcVDO lstrcat,<PUBLIC,FAR>
  168. ; parmD pDst
  169. ; parmD pSrc
  170. cBegin nogen
  171. call lstrsetup
  172. mov dx,di ; save original dest for return
  173. xor ax,ax ; get zero in ax
  174. mov cx,-1 ; at most 64 k to look
  175. repnz scasb ; look for end
  176. dec di ; Point at null byte
  177. ifndef WOW
  178. jmp lcp1 ; jump to lstrcpy loop
  179. else
  180. lcp1_wow: lodsb
  181. stosb
  182. or al,al
  183. jnz lcp1_wow
  184. ; normal lstrcat is now complete.
  185. ;
  186. ; Now begins a GROSS HACK HACK HACK for fixing wordperfect
  187. ; For compatibility reasons we want to check if the function call
  188. ; was of type lstrcat(lpsz, ".WRS");
  189. ;
  190. ; the checks are:
  191. ; let lpDest = ".WRS"
  192. ; if (lstrlen(lpDest)+NULLCHAR == 5) &&
  193. ; !lstrcmp(lpDest, ".WRS")) {
  194. ; if (wordperfect) {
  195. ; remove all backslashes in lpsz
  196. ; }
  197. ; }
  198. ;
  199. ; we do these checks after the concatenation 'cause it means that
  200. ; source string is valid and we wont GP fault while accessing the
  201. ; source string
  202. ; - Nanduri
  203. sub si, 5
  204. cmp si, ss:[bx+4]
  205. jnz @F
  206. cmp [si], 'W.' ; ".W"
  207. jnz @F
  208. cmp [si+2], 'SR' ; "RS"
  209. jnz @F
  210. lscat_DOTWRS:
  211. ; here if lstrcat (lpString, ".WRS")
  212. ; now make sure that it is wordperfect. this is a gross hack so
  213. ; why care for efficiency.
  214. push dx
  215. call MyGetAppWOWCompatFlags
  216. test dx, word ptr cs:[gacf_dotwrs+2]
  217. pop dx
  218. jz @F
  219. jmp short replace_slashes
  220. gacf_dotwrs:
  221. DD WOWCF_SANITIZEDOTWRSFILES
  222. replace_slashes:
  223. ; yes it is. strip backslashes if any.
  224. ; if there are any backslashes the lpString would be of the form
  225. ; \\blahblah or \\blah\blah. note that 'blah' is not important, the
  226. ; backslashes are.
  227. ;
  228. push es
  229. pop ds
  230. mov si, dx
  231. mov di, dx
  232. slash_a_slash:
  233. lodsb
  234. cmp al, '\'
  235. je slash_a_slash
  236. stosb
  237. or al, al
  238. jnz slash_a_slash
  239. @@:
  240. xchg ax,dx ; return ds:ax = original dest
  241. mov dx,es
  242. jmp lstrfinish
  243. endif
  244. cEnd nogen
  245. ;
  246. ;lstrOriginal: This is language independent version of lstrcmp
  247. ; specially made for kernel.
  248. ; (i made it case insensitive...chrisp)
  249. ;
  250. cProcVDO lstrOriginal,<PUBLIC,FAR>
  251. ; parmD ps1
  252. ; parmD ps2
  253. cBegin nogen
  254. call lstrsetup
  255. lcmploop:
  256. xor ax,ax
  257. cmp es:byte ptr [di],al
  258. jz ldidone ; left hand side finished <=
  259. cmp byte ptr [si],al
  260. jz lsismall ; right hand side finished, >
  261. lodsb
  262. ifdef FE_SB
  263. call MyIsDBCSLeadByte
  264. jc cmp1
  265. mov ah,ds:[si]
  266. inc si
  267. jmp short cmp2
  268. endif
  269. cmp1: call MyLower
  270. xor ah,ah
  271. cmp2: mov bx,ax
  272. mov al,es:[di]
  273. inc di
  274. ifdef FE_SB
  275. call MyIsDBCSLeadByte
  276. jc cmp3
  277. mov ah,es:[di]
  278. inc di
  279. jmp short cmp4
  280. endif
  281. cmp3: call MyLower
  282. xor ah,ah
  283. cmp4: cmp ax,bx ; effectlively es:[di],ds:[si]
  284. jz lcmploop ; still equal
  285. mov ax,0 ; preverve flags
  286. jb ldismall ; di is less than si
  287. lsismall:
  288. inc ax
  289. jmp short lstrcmpend
  290. ldidone:
  291. cmp byte ptr ds:[si],0
  292. jz lequal
  293. ldismall:
  294. dec ax
  295. lequal:
  296. lstrcmpend:
  297. jmp lstrfinish
  298. cEnd nogen
  299. end_fault_trap
  300. ;--------------------------------------------------------
  301. ;
  302. ; ANSI compatible string routines
  303. ;
  304. public AnsiUpper, AnsiLower, AnsiPrev, AnsiNext
  305. AnsiUpper:
  306. mov cl,ANSIUPPER_ID
  307. jmpnext
  308. AnsiLower:
  309. mov cl,ANSILOWER_ID
  310. jmpnext
  311. AnsiPrev:
  312. mov cl,ANSIPREV_ID
  313. jmpnext
  314. AnsiNext:
  315. mov cl,ANSINEXT_ID
  316. jmpnext end
  317. xor ch,ch
  318. if ROM
  319. push ds
  320. SetKernelDS
  321. endif
  322. cmp pStringFunc.sel,0 ; Is there a USER around?
  323. jz no_user_function
  324. if ROM
  325. push bp
  326. mov bp,sp
  327. push pStringFunc.sel
  328. push pStringFunc.off
  329. mov ds,[bp][2]
  330. UnSetKernelDS
  331. mov bp,[bp]
  332. retf 4
  333. else
  334. jmp pStringFunc
  335. endif
  336. no_user_function:
  337. if KDEBUG
  338. int 3
  339. endif
  340. if ROM
  341. pop ds
  342. UnSetKernelDS
  343. endif
  344. cmp cl,ANSIPREV_ID
  345. jz @F
  346. retf 4
  347. @@: retf 8
  348. ;----------------------------------------------------------------------------
  349. ; MyUpper: Called from LDSelf.ASM
  350. ; convert lower case to upper, must preserve es,di,cx
  351. ;---------------------------------------------------------------------------
  352. public MyUpper
  353. MyUpper:
  354. cmp al,'a'
  355. jb myu2
  356. cmp al,'z'
  357. jbe myu1
  358. ifdef FE_SB
  359. push ds
  360. SetKernelDS
  361. cmp [fFarEast],1 ; Far east ?
  362. pop ds
  363. UnSetKernelDS
  364. jge myu2 ; yes do nothing to the Microsoft fonts.
  365. endif
  366. cmp al,0E0H ; this is lower case a with a back slash
  367. jb myu2
  368. cmp al, 0F7H ; This is division mark in Microsoft fonts; So, don't
  369. je myu2 ; convert this; Fix for Bug #1356 -SANKAR-08-28-89;
  370. cmp al,0FEH
  371. ja myu2
  372. myu1: sub al,'a'-'A'
  373. myu2: ret
  374. ;----------------------------------------------------------------------------
  375. ; MyLower: Called from Atom.asm, LdOpen.asm, ldUtil.asm, ldself.asm
  376. ; convert upper case to lower, must preserve es,di,cx
  377. ;----------------------------------------------------------------------------
  378. public MyLower
  379. MyLower:
  380. cmp al,'A'
  381. jb myl2
  382. cmp al,'Z'
  383. jbe myl1
  384. push ds
  385. SetKernelDS
  386. cmp [fFarEast],1 ; this is a far east kbd 1/12/87 linsh
  387. pop ds
  388. UnSetKernelDS
  389. jge myl2 ; yes do nothing to the 0C0H - 0DEH range
  390. cmp al,0C0H ; this is lower case a with a back slash
  391. jb myl2
  392. cmp al, 0D7H ; This is multiply mark in Microsoft fonts; So, don't
  393. je myl2 ; translate this; Fix for Bug #1356;-SANKAR-08-28-89;
  394. cmp al,0DEH
  395. ja myl2
  396. myl1: add al,'a'-'A'
  397. myl2: ret
  398. ;-----------------------------------------------------------------------;
  399. ; IsDBCSLeadByte ;
  400. ;
  401. ; This Function will be exist on US Windows, but it
  402. ; returns FALSE always.
  403. ;
  404. ;-----------------------------------------------------------------------;
  405. cProc IsDBCSLeadByte,<PUBLIC,FAR>
  406. ; parmW char ss:[bx+04]
  407. cBegin nogen
  408. ifdef FE_SB
  409. mov bx,sp
  410. push ds
  411. SetKernelDS
  412. ;; push di
  413. ;;
  414. ;; mov ax,ss:[bx+04]
  415. ;; call MyIsDBCSLeadByte
  416. ;; jnc id1
  417. ;; xor ax,ax
  418. ;; jmp idx
  419. ;;id1: mov ax,1
  420. ;;idx:
  421. ;;
  422. ;; pop di
  423. mov al, byte ptr ss:[bx+4]
  424. mov bx, offset fDBCSLeadTable
  425. xlat
  426. xor ah,ah
  427. pop ds
  428. UnSetKernelDS
  429. else
  430. xor ax,ax
  431. endif
  432. ret 2
  433. cEnd nogen
  434. ifdef FE_SB
  435. ; This API returns DBCS lead byte table for applications which
  436. ; in turn can speed up DBCS checking without making calls to
  437. ; IsDBCSLeadByte.
  438. ;-----------------------------------------------------------------------;
  439. ; GetDBCSEnv ;
  440. ;
  441. ; int GetDBCSEnv(LPSTR lpsz, int cbMax)
  442. ; lpsz: long ptr points to buffer to receive DBCS lead byte table
  443. ; cbMax: how many bytes the buffer pointed to by lpsz.
  444. ; 0 if inquire buffer size required to receive the table
  445. ; return (ax) 0 if failed else the size of the table.
  446. ; use: AX, BX, CX, DX
  447. ;
  448. ;
  449. ;-----------------------------------------------------------------------;
  450. ;
  451. cProc GetDBCSEnv,<PUBLIC,FAR>
  452. ; parmD ss:[bx+6] ;lpsz
  453. ; parmW ss:[bx+4] ;cbMax
  454. cBegin nogen
  455. mov bx,sp ;frame ptr
  456. push es
  457. push di
  458. push si
  459. ;;; 12 bytes should be enough to accumulate our result.
  460. ;;; However, if fDBCSLeadTable corrupt then we are dead!!!!
  461. sub sp,12 ;temp private storage
  462. mov si,sp ;
  463. SetKernelDS es ;
  464. mov di, offset fDBCSLeadTable ;
  465. cld
  466. mov al,1 ;
  467. mov cx,256 ;256 bytes in table
  468. GDE_loop:
  469. xor al,1 ;toggle the match pattern (0/1)
  470. repe scasb ;
  471. jz GDE_done ;not found then CX must be 0
  472. mov ah,cl ;calc the index
  473. sub ah,255
  474. neg ah
  475. sub ah,al ;
  476. mov ss:[si],ah ;save it
  477. inc si
  478. jmps GDE_loop
  479. GDE_done:
  480. mov word ptr ss:[si],0 ;terminated with 0,0
  481. mov ax,si
  482. sub ax,sp ;how many bytes we got?
  483. jz GDE_Exit ;none, return
  484. add ax,2 ;count the terminated bytes
  485. inc si ;and advance ptr to the last 0
  486. mov cx,ss:[bx+4] ;get cbMax
  487. jcxz GDE_Exit ;return if inquire buffer size
  488. cmp cx,ax ;enough buffer provided ?
  489. jge @F
  490. xor ax,ax ;no, return error
  491. jmps GDE_Exit
  492. @@:
  493. beg_fault_trap GDE_gp
  494. les di, ss:[bx+6] ;lpsz
  495. mov cx,ax ;how many bytes to copy
  496. add di,ax
  497. dec di ;offset started from 0
  498. std
  499. rep movs byte ptr [di],ss:[si]
  500. end_fault_trap
  501. GDE_Exit:
  502. cld
  503. UnSetKernelDS es
  504. add sp, 12
  505. pop si
  506. pop di
  507. pop es
  508. ret 6
  509. cEnd nogen
  510. GDE_gp:
  511. fault_fix_stack
  512. xor ax, ax ;invalide lpsz, return ax=0
  513. jmps GDE_Exit
  514. ;--------------------------------------------------------------------------
  515. ;
  516. ; return carry clear if character in AL is first byte of DBCS
  517. ;
  518. ;--------------------------------------------------------------------------
  519. public MyIsDBCSLeadByte
  520. MyIsDBCSLeadByte:
  521. push ds
  522. SetKernelDS
  523. push ax ; Save AX for caller
  524. push bx ; Save BX for caller
  525. mov bx, offset fDBCSLeadTable
  526. xlat
  527. shr al,1 ; refrect to carry flag
  528. cmc
  529. pop bx
  530. pop ax
  531. ;; cmp [fFarEast],1 ; not in far east?
  532. ;; jb ikx ; carry set if not far east keyboard
  533. ;; mov cx,[KeyInfo].kbRanges.lo
  534. ;; cmp cl,ch
  535. ;; ja iknk ; lower range invalid, not kanji
  536. ;; cmp al,cl
  537. ;; jb ik1 ; below lower range, try second range
  538. ;; cmp al,ch
  539. ;; jbe ikgk ; inside lower range, valid kanji char
  540. ;;
  541. ;;ik1: mov cx,[KeyInfo].kbRanges.hi
  542. ;; cmp cl,ch ; valid upper range?
  543. ;; ja iknk ; no, not kanji
  544. ;; cmp al,cl ; is it within range?
  545. ;; jb ikx ; trick...carry already set
  546. ;; cmp al,ch
  547. ;; ja iknk
  548. ;;ikgk: clc ; within range...valid kanji char
  549. ;; jmp short ikx
  550. ;;
  551. ;;iknk: stc
  552. ;;ikx:
  553. ;; pop cx
  554. pop ds
  555. UnSetKernelDS
  556. ret
  557. public FarMyIsDBCSLeadByte
  558. FarMyIsDBCSLeadByte proc far
  559. call MyIsDBCSLeadByte
  560. ret
  561. FarMyIsDBCSLeadByte endp
  562. public MyIsDBCSTrailByte
  563. MyIsDBCSTrailByte proc near
  564. ;----------------------------------------------------------
  565. ; IsDBCSTrailByte
  566. ; Check if the indexed byte is a DBCS char trailing byte.
  567. ;
  568. ; Input:
  569. ; ES:SI = char *ach[]
  570. ; ES:DI -> position of character of interested.
  571. ;
  572. ; Output:
  573. ; Carry flag clear if it is a DBCS trailing byte
  574. ; Carry flag set if it is a SBCS or DBCS leading byte
  575. ;
  576. ; Use:
  577. ; flags
  578. ;
  579. ;----------------------------------------------------------
  580. cmp si,di ;if beginning >= index?
  581. jae IDTB_Exit ;yes, SBCS or DBCS 1st (CF=1)
  582. push si
  583. push ax
  584. cld ;no chance
  585. @@:
  586. lods byte ptr es:[si] ;
  587. call MyIsDBCSLeadByte
  588. cmc
  589. adc si,0 ;si++ if DBCS
  590. cmp di,si ;hit the target yet?
  591. ja @B ;go to loop if not yet
  592. pop ax ;di=si, we have a SBCS or DBCS 1st
  593. pop si ;di < si, we have a DBCS 2nd
  594. IDTB_Exit:
  595. cmc
  596. ret
  597. MyIsDBCSTrailByte endp
  598. ;---------------------------------------------------------------
  599. public FarMyIsDBCSTrailByte
  600. FarMyIsDBCSTrailByte proc far
  601. call MyIsDBCSTrailByte
  602. ret
  603. FarMyIsDBCSTrailByte endp
  604. endif ; FE_SB
  605. sEnd CODE
  606. end