Leaked source code of windows server 2003
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.

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