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.

721 lines
25 KiB

  1. ;++
  2. ;
  3. ; WOW v1.0
  4. ;
  5. ; Copyright (c) 1991, Microsoft Corporation
  6. ;
  7. ; WINLANG.ASM
  8. ; Win16 language-dependent string services
  9. ;
  10. ; History:
  11. ;
  12. ; Created 18-Jun-1991 by Jeff Parsons (jeffpar)
  13. ; Copied from WIN31 and edited (as little as possible) for WOW16
  14. ;--
  15. ;****************************************************************************
  16. ;* *
  17. ;* WinLang.ASM - *
  18. ;* *
  19. ;* API calls to support different lanuages *
  20. ;* *
  21. ;****************************************************************************
  22. NOTEXT = 1
  23. .xlist
  24. include user.inc
  25. .list
  26. ExternFP AllocSelector
  27. ExternFP FreeSelector
  28. ExternFP PrestoChangoSelector
  29. ExternNP IAnsiPrev
  30. ExternNP IAnsiNext
  31. ;****************************************************************************
  32. ;* *
  33. ;* WOW note: The implementations in this file are the US implementations *
  34. ;* with all the language driver and DBCS stuff ripped out. *
  35. ;* PatchUserStrRtnsToThunk, at the bottom of this file, is *
  36. ;* called during startup of user16 if the locale is other *
  37. ;* than U.S. English, or if forced to thunk by a registry key. *
  38. ;* This routine patches each of the APIs implemented here to *
  39. ;* simply jump to the thunk, with a name beginning "Win32". *
  40. ;* *
  41. ;* The StrRtnsPatchTable defined below controls the patching. *
  42. ;* *
  43. ;****************************************************************************
  44. ExternNP Win32lstrcmp
  45. ExternNP Win32lstrcmpi
  46. ExternNP Win32AnsiPrev
  47. ExternNP Win32AnsiNext
  48. ExternNP Win32AnsiUpper
  49. ExternNP Win32AnsiLower
  50. ExternNP Win32AnsiUpperBuff
  51. ExternNP Win32AnsiLowerBuff
  52. ExternNP Win32IsCharAlpha
  53. ExternNP Win32IsCharAlphaNumeric
  54. ExternNP Win32IsCharUpper
  55. ExternNP Win32IsCharLower
  56. sBegin DATA
  57. LabelW StrRtnsPatchTable
  58. ; Location of patch Target of jmp patched in
  59. ; ----------------- ------------------------
  60. dw codeOffset Ilstrcmp, codeOffset Win32lstrcmp
  61. dw codeOffset Ilstrcmpi, codeOffset Win32lstrcmpi
  62. ;
  63. ; These two functions need to be thunked only for DBCS builds
  64. ;
  65. ifdef FE_SB
  66. dw codeOffset IAnsiPrev, codeOffset Win32AnsiPrev
  67. dw codeOffset IAnsiNext, codeOffset Win32AnsiNext
  68. endif ; FE_SB
  69. dw codeOffset IAnsiUpper, codeOffset Win32AnsiUpper
  70. dw codeOffset IAnsiLower, codeOffset Win32AnsiLower
  71. dw codeOffset IAnsiUpperBuff, codeOffset Win32AnsiUpperBuff
  72. dw codeOffset IAnsiLowerBuff, codeOffset Win32AnsiLowerBuff
  73. dw codeOffset IsCharAlpha, codeOffset Win32IsCharAlpha
  74. dw codeOffset IsCharAlphaNumeric, codeOffset Win32IsCharAlphaNumeric
  75. dw codeOffset IsCharUpper, codeOffset Win32IsCharUpper
  76. dw codeOffset IsCharLower, codeOffset Win32IsCharLower
  77. LabelW StrRtnsPatchTableEnd
  78. sEnd
  79. createSeg _TEXT, CODE, WORD, PUBLIC, CODE
  80. sBegin CODE
  81. assumes CS, CODE
  82. assumes DS, DATA
  83. ExternNP MyUpper
  84. ExternNP MyLower
  85. ExternNP MyAnsiUpper
  86. ExternNP MyAnsiLower
  87. ;--------------------------------------------------------------------------
  88. ;
  89. ; The following table contains the primary and secondary weight info.
  90. ;
  91. ; For alphanumeric characters primary weight is equal to (Ascii + PrimeWt)
  92. ; Secondary weight is either 0 or 1 (For all upper case letters zero and
  93. ; lower case letters 1);
  94. ;
  95. ; For non-alphanumeric characters, primary weight is their ASCII value and
  96. ; the secondary weight is zero.
  97. ;
  98. ; Note that the primary weight calculated with this table for the smallest
  99. ; of the alpha-numeric character('0') is 100h (30h+D0h), which is more than
  100. ; the primary weight of the highest non-alpha-numeric character FFh;
  101. ; Thus all non-alpha-numeric characters will sort before any alpha-numeric
  102. ; characters;
  103. ;
  104. ; Note that 'PrimeWt' field for lowercase letters is B0h instead of
  105. ; D0h because when added with their ascii, it should become exactly
  106. ; equal to the primary weights of their upper-case counterparts;
  107. ;
  108. ; IMPORTANT NOTE: On 01-17-90, we came across a bug in lstrcmpi() due to
  109. ; the fact that we are not treating characters C0h to FEh as upper and
  110. ; lower case alphas; So, I added some more ranges to the SortStruc table
  111. ; to map the range C0h to D6h onto the range E0h to F6 and to map the
  112. ; range D8h to DEh onto the range F8h to FEh. A value of 20h in the PrimeWt
  113. ; field automatically takes care of this mapping because that is the diff
  114. ; to be added to the uppercase letter to make it lowercase; The secondary
  115. ; weights are as usual 0 for uppercase and 1 for lowercase;
  116. ; --Fix for Bug #8222 --01-17-90-- SANKAR --
  117. ;--------------------------------------------------------------------------
  118. SortStruct STRUC
  119. StartAscii db ?
  120. EndAscii db ?
  121. PrimeWt db ?
  122. SecondWt db ?
  123. SortStruct ENDS
  124. public SortTable
  125. LabelB SortTable
  126. SortStruct <'0', '9', 0D0h, 0>
  127. SortStruct <'A', 'Z', 0D0h, 0>
  128. SortStruct <'a', 'z', 0B0h, 1>
  129. SortStruct <0C0h, 0D6h, 20h, 0>
  130. SortStruct <0D8h, 0DEh, 20h, 0>
  131. SortStruct <0E0h, 0F6h, 0, 1>
  132. SortStruct <0F8h, 0FEh, 0, 1>
  133. LabelB SortTableEnd
  134. ;*----------------------------------------------------------------------*
  135. ;* *
  136. ;* GetWeightValues() *
  137. ;* Input: *
  138. ;* AL = character whose weight values are asked for *
  139. ;* Output: *
  140. ;* AX = Primary weight of the character *
  141. ;* BL = Secondary weight of the character *
  142. ;*----------------------------------------------------------------------*
  143. public GetWeightValues
  144. GetWeightValues PROC NEAR
  145. xor ah, ah
  146. xor bx, bx ; Index into the table
  147. ; Enter the number of entries in the sort table.
  148. mov cx, (SortTableEnd - SortTable)/(SIZE SortStruct)
  149. gwv_loop:
  150. cmp al, byte ptr SortTable[bx].StartAscii
  151. jb gwv_end
  152. cmp al, byte ptr SortTable[bx].EndAscii
  153. jbe gwv_GetWeights
  154. add bx, SIZE SortStruct
  155. loop gwv_loop
  156. jmps gwv_end
  157. gwv_GetWeights:
  158. add al, byte ptr SortTable[bx].PrimeWt
  159. adc ah, 0
  160. mov bl, byte ptr SortTable[bx].SecondWt
  161. gwv_end:
  162. ret
  163. GetWeightValues ENDP
  164. ;*--------------------------------------------------------------------------*
  165. ;* *
  166. ;* lstrcmp(String1, String2) - *
  167. ;* *
  168. ;* String1 and String2 are LPSTR's to null terminated strings. *
  169. ;* *
  170. ;* This function returns -1 if String1 sorts before String2, 0 if String1*
  171. ;* and String2 have the same sorting and 1 if String2 sorts before *
  172. ;* String1. *
  173. ;* NOTE: This is case sensitive compare. *
  174. ;* *
  175. ;* Outside the U.S. English locale, this function is patched to be a *
  176. ;* near jump to Win32lstrcmp, aka WU32lstrcmp. *
  177. ;* *
  178. ;*--------------------------------------------------------------------------*
  179. cProc Ilstrcmp, <FAR, PUBLIC>, <SI, DI>
  180. ; ^^^^^^^^ US_lstrcmp assumes SI, DI saved!
  181. ParmD lpStr1
  182. ParmD lpStr2
  183. LocalB SecWeight1 ; Locals used by US_lstrcmp
  184. LocalB SecWeight2
  185. LocalB LocSecWeight
  186. LocalB fCaseSensitive ; Flag indicating whether it is case sensitive or not.
  187. cBegin
  188. mov byte ptr fCaseSensitive, 1 ; Yup! It is case sensitive
  189. call US_lstrcmp
  190. cEnd
  191. ;*----------------------------------------------------------------------*
  192. ;* *
  193. ;* US_lstrcmp *
  194. ;* US version of string sort(Case sensitive); *
  195. ;* Uses locals defined by Ilstrcmp above.
  196. ;* To understand the algorithm, read the comments for SortStruct *
  197. ;* *
  198. ;*----------------------------------------------------------------------*
  199. public US_lstrcmp
  200. US_lstrcmp PROC NEAR
  201. push ds ; Save ds
  202. ;Initialise the secondary wt values
  203. mov byte ptr SecWeight1, 0
  204. mov byte ptr SecWeight2, 0
  205. ; Load both the strings
  206. lds si, lpStr1
  207. les di, lpStr2
  208. ss_loop:
  209. ; Take one char from both the strings.
  210. mov al, byte ptr ds:[si]
  211. xor ah, ah ; make secondary wts zero
  212. mov dl, byte ptr es:[di]
  213. xor dh, dh
  214. inc si ; Move to next character
  215. inc di
  216. cmp al, 0
  217. jz ss_chkprimary ; Check if lpStr1 has ended
  218. cmp dl, 0
  219. jz ss_chkprimary ; Check if lpStr2 has ended
  220. ; Let us compare the ASCII vaues
  221. ; If the asciis are equal, then weights are equal
  222. cmp al, dl
  223. je ss_loop ; Goto next character
  224. ; Now, the asciis differ. So, let us find the weights
  225. ; Let us get the weights for the character of lpStr1 (in ax )
  226. call GetWeightValues
  227. ; ax contains the primary weight of char of lpStr1
  228. ; bl contains the secondary weight of ditto
  229. mov LocSecWeight, bl
  230. xchg ax, dx
  231. call GetWeightValues
  232. ; compare primary weights
  233. ; Primary weight of Str1 in DX and Str2 in AX
  234. cmp ax, dx
  235. jb CompareRetGT
  236. ja CompareRetLT
  237. ; Check if it is Case-Insensitive compare
  238. mov bh, fCaseSensitive
  239. or bh, bh
  240. jz ss_loop ; It is case-insensitive; So, no need to consider
  241. ; the secondary weightages. Goto next character.
  242. ; Control comes here only if it is a case sensitive compare.
  243. ; Now, primaries are equal. Compare secondaries
  244. mov bh, LocSecWeight
  245. cmp bh, bl
  246. je ss_loop ; Secondaries are equal, Continue
  247. ; Secondaries are not equal. Check if they are stored already
  248. mov cl, SecWeight1
  249. or cl, SecWeight2
  250. jnz ss_loop ; Secondaries already exist, continue
  251. ; Secondaries haven't been saved sofar.Save the secondaries
  252. mov SecWeight1, bh
  253. mov SecWeight2, bl
  254. jmps ss_loop ; Process the next character
  255. ss_chkprimary:
  256. ; al, dl contain the primary weights and at least one of them is
  257. ; zero.
  258. cmp al, 0
  259. ja CompareRetGT
  260. cmp dl, 0
  261. ja CompareRetLT
  262. ; both are zero; they are equal; So, check the secondary values
  263. mov bl, SecWeight1
  264. cmp bl, SecWeight2
  265. ja CompareRetGT
  266. jb CompareRetLT
  267. ; They are identical with equal weightages
  268. xor ax, ax
  269. jmps CompareRet
  270. CompareRetGT:
  271. mov ax, 1
  272. jmps CompareRet
  273. CompareRetLT:
  274. mov ax, -1
  275. CompareRet:
  276. pop ds
  277. ret
  278. US_lstrcmp ENDP
  279. ;*--------------------------------------------------------------------------*
  280. ;* *
  281. ;* lstrcmpi(String1, String2) - *
  282. ;* (Case Insensitive compare) *
  283. ;* String1 and String2 are LPSTR's to null terminated strings. *
  284. ;* *
  285. ;* This function returns -1 if String1 sorts before String2, 0 if String1*
  286. ;* and String2 have the same sorting and 1 if String2 sorts before *
  287. ;* String1. *
  288. ;* *
  289. ;* Outside the U.S. English locale, this function is patched to be a *
  290. ;* near jump to Win32lstrcmpi, aka WU32lstrcmpi. *
  291. ;* *
  292. ;*--------------------------------------------------------------------------*
  293. cProc Ilstrcmpi, <FAR, PUBLIC>, <SI, DI>
  294. ; ^^^^^^^^ US_lstrcmp assumes SI, DI saved!
  295. ParmD lpStr1
  296. ParmD lpStr2
  297. LocalB SecWeight1 ; Locals used by US_lstrcmp
  298. LocalB SecWeight2
  299. LocalB LocSecWeight
  300. LocalB fCaseSensitive ; Flag indicating whether it is case sensitive or not.
  301. cBegin
  302. mov byte ptr fCaseSensitive, 0 ; FALSE => Case-Insensitive.
  303. call US_lstrcmp
  304. cEnd
  305. ;*----------------------------------------------------------------------*
  306. ;* *
  307. ;* AnsiUpper implementation is from Win3.1 US_AnsiUpper() *
  308. ;* *
  309. ;* Outside the U.S. English locale, this function is patched to be a *
  310. ;* near jump to Win32AnsiUpper, aka WU32AnsiUpper. *
  311. ;* *
  312. ;*----------------------------------------------------------------------*
  313. cProc IAnsiUpper, <FAR, PUBLIC, PASCAL>, <SI, DI>
  314. ParmD lpStr
  315. cBegin
  316. les di,lpStr
  317. mov cx,es
  318. mov ax,di
  319. call MyUpper ; if passed a char, just upper case it.
  320. jcxz au1
  321. inc cx ; take care of the case of sign propagation
  322. jz au1
  323. dec cx
  324. call MyAnsiUpper ; otherwise upper case the whole string
  325. mov ax, word ptr lpStr ; Now, dx:ax points at original string
  326. au1: mov dx,es
  327. cEnd
  328. ;*----------------------------------------------------------------------*
  329. ;* *
  330. ;* AnsiLower implementation is from Win3.1 US_AnsiLower() *
  331. ;* *
  332. ;* Outside the U.S. English locale, this function is patched to be a *
  333. ;* near jump to Win32AnsiLower, aka WU32AnsiLower. *
  334. ;* *
  335. ;*----------------------------------------------------------------------*
  336. cProc IAnsiLower, <FAR, PUBLIC, PASCAL>, <SI, DI>
  337. ParmD lpStr
  338. cBegin
  339. les di,lpStr
  340. mov cx,es
  341. mov ax,di
  342. call MyLower ; if passed a char, just lower case it.
  343. jcxz al1
  344. inc cx ; take care of the case of sign propagation
  345. jz al1
  346. dec cx
  347. call MyAnsiLower ; otherwise lower case the whole string
  348. mov ax, word ptr lpStr ; dx:ax points at original string
  349. al1: mov dx,es
  350. cEnd
  351. ;*----------------------------------------------------------------------*
  352. ;* *
  353. ;* AnsiUpperBuff implemented from Win3.1 US_AnsiUpperBuff *
  354. ;* *
  355. ;* Outside the U.S. English locale, this function is patched to be a *
  356. ;* near jump to Win32AnsiUpperBuff, aka WU32AnsiUpperBuff. *
  357. ;* *
  358. ;*----------------------------------------------------------------------*
  359. cProc IAnsiUpperBuff, <FAR, PUBLIC, PASCAL>, <SI, DI>
  360. ParmD lpStr
  361. ParmW iCount
  362. cBegin
  363. cld
  364. les di, lpStr
  365. mov si, di
  366. mov cx, iCount ; if iCount=0, the Buff size is 64K.
  367. mov dx, iCount ; Preserve the length of Buffer
  368. su_begin:
  369. lods byte ptr es:[si]
  370. call MyUpper
  371. stosb
  372. loop su_begin
  373. su_over:
  374. mov ax, dx ; Move the result to ax
  375. cEnd
  376. ;*----------------------------------------------------------------------*
  377. ;* *
  378. ;* AnsiLowerBuff implemented from Win3.1 US_AnsiLowerBuff *
  379. ;* *
  380. ;* Outside the U.S. English locale, this function is patched to be a *
  381. ;* near jump to Win32AnsiLowerBuff, aka WU32AnsiLowerBuff. *
  382. ;* *
  383. ;*----------------------------------------------------------------------*
  384. cProc IAnsiLowerBuff, <FAR, PUBLIC, PASCAL>, <SI, DI>
  385. ParmD lpStr
  386. ParmW iCount
  387. cBegin
  388. cld
  389. les di, lpStr
  390. mov si, di
  391. mov cx, iCount ; If cx=0, the buff size is 64K
  392. mov dx, cx ; Preserve the length in DX
  393. sl_begin:
  394. lods byte ptr es:[si]
  395. call MyLower
  396. stosb
  397. loop sl_begin
  398. sl_over:
  399. mov ax, dx ; Move the result to ax
  400. cEnd
  401. ;*----------------------------------------------------------------------*
  402. ;* *
  403. ;* IsCharLower implemented with Win3.1 US_IsCharLower *
  404. ;* *
  405. ;* Outside the U.S. English locale, this function is patched to be a *
  406. ;* near jump to Win32IsCharLower, aka WU32IsCharLower. *
  407. ;* *
  408. ;*----------------------------------------------------------------------*
  409. cProc IsCharLower, <FAR, PUBLIC, PASCAL>
  410. ParmB bChar
  411. cBegin
  412. mov al, bChar
  413. call Loc_Lower
  414. jc icl_end
  415. xor ax, ax ; Not lower. So, false
  416. icl_end:
  417. cEnd
  418. ;*----------------------------------------------------------------------*
  419. ;* *
  420. ;* IsCharUpper implemented with Win3.1 US_IsCharUpper *
  421. ;* *
  422. ;* Outside the U.S. English locale, this function is patched to be a *
  423. ;* near jump to Win32IsCharUpper, aka WU32IsCharUpper. *
  424. ;* *
  425. ;*----------------------------------------------------------------------*
  426. cProc IsCharUpper, <FAR, PUBLIC, PASCAL>
  427. ParmB bChar
  428. cBegin
  429. mov al, bChar
  430. call Loc_Upper
  431. jc icu_end
  432. xor ax, ax
  433. icu_end:
  434. cEnd
  435. ;*----------------------------------------------------------------------*
  436. ;* *
  437. ;* IsCharAlphaNumeric implemented with Win3.1 US_IsCharAlphaNumeric *
  438. ;* *
  439. ;* Outside the U.S. English locale, this function is patched to be a *
  440. ;* near jump to Win32IsCharAlphaNumeric, aka WU32IsCharAlphaNumeric. *
  441. ;* *
  442. ;*----------------------------------------------------------------------*
  443. cProc IsCharAlphaNumeric, <FAR, PUBLIC, PASCAL>
  444. ParmB bChar
  445. cBegin
  446. mov al, bChar
  447. call Loc_Numeric
  448. jc ica_end
  449. jmps ica_begin
  450. cEnd
  451. ;*----------------------------------------------------------------------*
  452. ;* *
  453. ;* IsCharAlpha implemented with Win3.1 US_IsCharAlpha *
  454. ;* *
  455. ;* Outside the U.S. English locale, this function is patched to be a *
  456. ;* near jump to Win32IsCharAlpha, aka WU32IsCharAlpha. *
  457. ;* *
  458. ;*----------------------------------------------------------------------*
  459. cProc IsCharAlpha, <FAR, PUBLIC, PASCAL>
  460. ParmB bChar
  461. cBegin
  462. mov al, bChar
  463. ica_begin:
  464. call Loc_Lower
  465. jc ica_end
  466. call Loc_Upper
  467. jc ica_end
  468. xor ax, ax
  469. ica_end:
  470. cEnd
  471. ;*----------------------------------------------------------------------*
  472. ;* *
  473. ;* Loc_Upper, LocLower, Loc_Numeric *
  474. ;* *
  475. ;* Used by IsCharXxx US implementations *
  476. ;* *
  477. ;* Input: *
  478. ;* AL = character being tested *
  479. ;* Output: *
  480. ;* Carry flag set if TRUE *
  481. ;* Carry flag cleared if FALSE *
  482. ;*----------------------------------------------------------------------*
  483. public Loc_Upper
  484. LabelNP <Loc_Upper>
  485. cmp al, 'A'
  486. jb Loc_False
  487. cmp al, 'Z'
  488. jbe Loc_True
  489. cmp al, 0C0h
  490. jb Loc_False
  491. cmp al, 0D7h ; This is multiply sign in Microsoft fonts, So, ignore;
  492. je Loc_False ; Fix for Bug #1356; SANKAR --08-28-89--;
  493. cmp al, 0DEh
  494. jbe Loc_True
  495. jmps Loc_False
  496. public Loc_Lower
  497. LabelNP <Loc_Lower>
  498. ; 0xDF and 0xFF are Lower case. But they don't have an equivalent
  499. ; upper case letters;
  500. ; So, they are treated as special case chars here
  501. ; Fix for Bug # 9799 --SANKAR-- 02-21-90 --
  502. cmp al, 0DFh
  503. je Loc_True
  504. cmp al, 0FFh
  505. je Loc_True
  506. ; Fall thro to the next function
  507. errnz ($-Loc_IsConvertibleToUpperCase)
  508. public Loc_IsConvertibleToUpperCase
  509. LabelNP <Loc_IsConvertibleToUpperCase>
  510. cmp al, 'a'
  511. jb Loc_False
  512. cmp al, 'z'
  513. jbe Loc_True
  514. cmp al, 0E0h
  515. jb Loc_False
  516. cmp al, 0F7h ; This is divide sign in Microsoft fonts; So, ignore
  517. je Loc_False; ; Fix for Bug #1356; SANKAR --08-28-89--;
  518. cmp al, 0FEh
  519. jbe Loc_True
  520. jmps Loc_False
  521. LabelNP <Loc_Numeric>
  522. cmp al, '0'
  523. jb Loc_False
  524. cmp al, '9'
  525. ja Loc_False
  526. Loc_True:
  527. stc ; Set carry to indicate true
  528. jmps Loc_End
  529. Loc_False:
  530. clc ; Clear carry to indicate false
  531. Loc_End:
  532. ret
  533. ;*----------------------------------------------------------------------*
  534. ;* *
  535. ;* PatchUserStrRtnsToThunk -- *
  536. ;* *
  537. ;*----------------------------------------------------------------------*
  538. cProc PatchUserStrRtnsToThunk, <PUBLIC, FAR, PASCAL>, <SI,DI>
  539. cBegin
  540. cCall AllocSelector, <0>
  541. cCall PrestoChangoSelector, <cs, ax>
  542. push ax
  543. pop es
  544. mov si, dataOffset StrRtnsPatchTable ; ds:si = StrRtnsPatchTable
  545. PatchLoop:
  546. lodsw
  547. mov di, ax ; di = offset of code to be patched
  548. mov ax, 0E9h ; opcode for near jump w/2 byte diff.
  549. stosb ; store jmp opcode
  550. lodsw
  551. sub ax, di ; difference between src and target
  552. sub ax, 2 ; encoded difference is based on
  553. ; address of next instruction
  554. stosw ; store difference
  555. cmp si, dataOffset StrRtnsPatchTableEnd
  556. jb PatchLoop
  557. xor ax, ax
  558. push es ; for FreeSelector
  559. push ax
  560. pop es
  561. call FreeSelector
  562. cEnd
  563. sEnd CODE
  564. end
  565.