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.

1502 lines
40 KiB

  1. .xlist
  2. include kernel.inc
  3. include gpfix.inc
  4. include pdb.inc
  5. include tdb.inc
  6. include newexe.inc
  7. include protect.inc
  8. .list
  9. .386
  10. ERROR_NO_MORE_ITEMS EQU 259
  11. ;-----------------------------------------------------------------------
  12. ;-----------------------------------------------------------------------
  13. ; App patching defines
  14. externFP RegCloseKey32
  15. externFP RegOpenKey32
  16. externFP RegEnumKey32
  17. externFP RegEnumValue32
  18. externFP FarGetCachedFileHandle
  19. externFP GlobalRealloc
  20. externFP GlobalSize
  21. externFP Far_genter
  22. externFP Far_gleave
  23. externFP Far_htoa0
  24. externFP Far_pdref
  25. externFP FreeSelector
  26. ; MultiThreading version of change PDB
  27. ;externFP GetCurPDB
  28. ;externFP SetCurPDB
  29. ;externFP TopPDB
  30. ; MultiThreading version of change PDB
  31. externW topPDB
  32. externW Win_PDB
  33. externW gdtdsc
  34. REG_BINARY equ 3
  35. HKEY_LOCAL_MACHINE equ 80000002h
  36. HKEY_LOCAL_MACHINE_HI equ 8000h
  37. HKEY_LOCAL_MACHINE_LO equ 0002h
  38. ; Under HKEY_LOCAL_MACHINE
  39. REGSTR_PATH_APPPATCH equ <"System\CurrentControlSet\Control\Session Manager\AppPatches">
  40. ; There is one value for each modification to a given segment.
  41. ; The values for a segment are stored under the key
  42. ; REGSTR_PATH_APPPATCH\<AppName>\<AppVersion>\<signature>
  43. ; where <signature> lists bytes in the module to match.
  44. BY_HANDLE_FILE_INFORMATION STRUC
  45. bhfi_dwFileAttributes DD ?
  46. bhfi_ftCreationTime DD 2 dup (?)
  47. bhfi_ftLastAccessTime DD 2 dup (?)
  48. bhfi_ftLastWriteTime DD 2 dup (?)
  49. bhfi_dwVolumeSerialNumber DD ?
  50. bhfi_nFileSizeHigh DD ?
  51. bhfi_nFileSizeLow DD ?
  52. bhfi_nNumberOfLinks DD ?
  53. bhfi_nFileIndexHigh DD ?
  54. bhfi_nFileIndexLow DD ?
  55. BY_HANDLE_FILE_INFORMATION ENDS
  56. ;-----------------------------------------------------------------------
  57. ; Signature definitions
  58. ;
  59. AP_SIG STRUC
  60. sig_format DB ? ; formatType for the struc
  61. ; rest of the data depends on the value in the sig_format field
  62. AP_SIG ENDS
  63. ; Supported values for the sig_format field
  64. AP_SIG_FORMAT_HEXE equ 01h ; match hExe bytes, 1B offset
  65. AP_SIG_FORMAT_HEXE2 equ 02h ; match hExe bytes, 2B offset
  66. AP_SIG_FORMAT_FILE2 equ 03h ; match file bytes, 2B offset
  67. AP_SIG_FORMAT_FILE3 equ 04h ; match file bytes, 3B offset
  68. AP_SIG_FORMAT_FILE4 equ 05h ; match file bytes, 4B offset
  69. AP_SIG_FORMAT_FILESIZE2 equ 06h ; match file size, 2B size
  70. AP_SIG_FORMAT_FILESIZE3 equ 07h ; match file size, 3B size
  71. AP_SIG_FORMAT_FILESIZE4 equ 08h ; match file size, 4B size
  72. AP_SIG_FORMAT_META equ 0ffh ; contains other signatures
  73. ;AP_SIG_FORMAT_HEXE
  74. AP_SIG_HEXE STRUC
  75. es_format DB ? ; AP_SIG_FORMAT_HEXE
  76. ; There can be multiple signature strings, packed one after the other.
  77. ; All must match to give a match.
  78. ; cb==0 signals the end.
  79. es_cb DB ? ; number of bytes to compare
  80. es_offset DB ? ; offset to begin signature compare
  81. es_abSignature DB ? ; cb DUP (?) ; signature bytes
  82. AP_SIG_HEXE ENDS
  83. ;AP_SIG_FORMAT_HEXE2
  84. AP_SIG_HEXE2 STRUC
  85. es2_format DB ? ; AP_SIG_FORMAT_HEXE2
  86. ; There can be multiple signature strings, packed one after the other.
  87. ; All must match to give a match.
  88. ; cb==0 signals the end.
  89. es2_cb DB ? ; number of bytes to compare
  90. es2_offset DW ? ; offset to begin signature compare
  91. es2_abSignature DB ? ; cb DUP (?) ; signature bytes
  92. AP_SIG_HEXE2 ENDS
  93. ;AP_SIG_FORMAT_FILE2
  94. AP_SIG_FILE2 STRUC
  95. fs2_format DB ? ; AP_SIG_FORMAT_FILE2
  96. ; There can be multiple signature strings, packed one after the other.
  97. ; All must match to give a match.
  98. ; cb==0 signals the end.
  99. fs2_cb DB ? ; number of bytes to compare
  100. fs2_offset DB 2 DUP (?) ; offset to begin signature compare
  101. fs2_abSignature DB ? ; cb DUP (?) ; bytes to match
  102. AP_SIG_FILE2 ENDS
  103. ;AP_SIG_FORMAT_FILE3
  104. AP_SIG_FILE3 STRUC
  105. fs3_format DB ? ; AP_SIG_FORMAT_FILE3
  106. ; There can be multiple signature strings, packed one after the other.
  107. ; All must match to give a match.
  108. ; cb==0 signals the end.
  109. fs3_cb DB ? ; number of bytes to compare
  110. fs3_offset DB 3 DUP (?) ; offset to begin signature compare
  111. fs3_abSignature DB ? ; cb DUP (?) ; bytes to match
  112. AP_SIG_FILE3 ENDS
  113. ;AP_SIG_FORMAT_FILE4
  114. AP_SIG_FILE4 STRUC
  115. fs4_format DB ? ; AP_SIG_FORMAT_FILE4
  116. ; There can be multiple signature strings, packed one after the other.
  117. ; All must match to give a match.
  118. ; cb==0 signals the end.
  119. fs4_cb DB ? ; number of bytes to compare
  120. fs4_offset DB 4 DUP (?) ; offset to begin signature compare
  121. fs4_abSignature DB ? ; cb DUP (?) ; bytes to match
  122. AP_SIG_FILE4 ENDS
  123. ;AP_SIG_FORMAT_FILESIZE
  124. AP_SIG_FILESIZE STRUC
  125. fss_format DB ? ; AP_SIG_FORMAT_FILESIZE[2,3,4]
  126. fss_cbFile DB ? ; file size in bytes
  127. AP_SIG_FILESIZE ENDS
  128. ;AP_SIG_FORMAT_FILESIZE2
  129. AP_SIG_FILESIZE2 STRUC
  130. fss2_format DB ? ; AP_SIG_FORMAT_FILESIZE2
  131. fss2_cbFile DB 2 DUP (?) ; file size in bytes
  132. AP_SIG_FILESIZE2 ENDS
  133. ;AP_SIG_FORMAT_FILESIZE3
  134. AP_SIG_FILESIZE3 STRUC
  135. fss3_format DB ? ; AP_SIG_FORMAT_FILESIZE3
  136. fss3_cbFile DB 3 DUP (?) ; file size in bytes
  137. AP_SIG_FILESIZE3 ENDS
  138. ;AP_SIG_FORMAT_FILESIZE4
  139. AP_SIG_FILESIZE4 STRUC
  140. fss4_format DB ? ; AP_SIG_FORMAT_FILESIZE4
  141. fss4_cbFile DB 4 DUP (?) ; file size in bytes
  142. AP_SIG_FILESIZE4 ENDS
  143. ;AP_SIG_FORMAT_META
  144. AP_SIG_META STRUC
  145. ms_format DB ? ; AP_SIG_FORMAT_META
  146. ; There can be multiple sub-signatures, packed one after the other.
  147. ; All must match to give a match.
  148. ; cb==0 signals the end.
  149. ms_cb DB ? ; number of bytes in the sub-signature
  150. ms_abSubSignature DB ? ; the sub-signature
  151. AP_SIG_META ENDS
  152. ;-----------------------------------------------------------------------
  153. ; Patch definitions
  154. ;
  155. AP_COMMON STRUC
  156. ap_format DB ? ; formatType for the struc
  157. ap_cbSize DB ? ; number of bytes in the whole struct
  158. ; rest of the data depends on the value in the ap_format field
  159. AP_COMMON ENDS
  160. ; Supported values for the ap_format field:
  161. AP_FORMAT_REPLACE equ 1
  162. AP_FORMAT_ADD equ 2
  163. ;AP_FORMAT_REPLACE
  164. AP_REPLACE STRUC
  165. apr_format DB ? ; AP_FORMAT_REPLACE
  166. apr_cbSize DB ? ; number of bytes in the whole struct
  167. apr_offset DW ? ; offset within the segment
  168. apr_cb DB ? ; number of bytes to replace
  169. apr_abOld DB ? ; cb DUP (?) ; old bytes
  170. apr_abNew DB ? ; cb DUP (?) ; new bytes
  171. AP_REPLACE ENDS
  172. ;AP_FORMAT_ADD
  173. AP_ADD STRUC
  174. apa_format DB ? ; AP_FORMAT_ADD
  175. apa_cbSize DB ? ; number of bytes in the whole struct
  176. apa_offset DW ? ; offset within the segment
  177. apa_cb DB ? ; number of bytes to replace
  178. apa_abNew DB ? ; cb DUP (?) ; new bytes
  179. AP_ADD ENDS
  180. DataBegin
  181. szREGSTR_PATH_APPPATCH db REGSTR_PATH_APPPATCH, "\", 0
  182. ; app-patching cache
  183. globalW hExePatchAppCache 0
  184. globalD hkeyPatchAppCache 0
  185. DataEnd
  186. sBegin NRESCODE
  187. assumes CS,NRESCODE
  188. ; GetPatchAppCache
  189. ;
  190. ; Gets an hkeyReg from the PatchApp cache if hExe in cache.
  191. ;
  192. ; Arguments:
  193. ; hExe
  194. ;
  195. ; Returns:
  196. ; dx:ax -1 if cache miss
  197. ; registry key associated with hExe if cache hit
  198. ;
  199. ; Registers Preserved:
  200. ; DI, SI, DS
  201. assumes ds,nothing
  202. assumes es,nothing
  203. ;HKEY
  204. cProc GetPatchAppCache, <PUBLIC, NEAR>, <ds>
  205. parmW hExe
  206. cBegin
  207. SetKernelDSNRes
  208. ; Set up dx==ax==-1 (indicates cache miss)
  209. sub ax, ax
  210. dec ax
  211. mov dx, ax
  212. mov cx, hExe
  213. cmp cx, hExePatchAppCache
  214. jne short gpac_exeunt
  215. mov dx, hkeyPatchAppCache.hi
  216. mov ax, hkeyPatchAppCache.lo
  217. krDebugOut DEB_WARN,"GetPatchAppCache: hit (#cx, #dx#ax)"
  218. gpac_exeunt:
  219. UnSetKernelDS
  220. cEnd
  221. ; AddPatchAppCache
  222. ;
  223. ; Adds an (hExe,hkeyReg) pair to the PatchApp cache.
  224. ;
  225. ; Arguments:
  226. ; hExe
  227. ; hkeyReg
  228. ;
  229. ; Returns:
  230. ;
  231. ;
  232. ; Registers Preserved:
  233. ; DI, SI, DS
  234. assumes ds,nothing
  235. assumes es,nothing
  236. ;VOID
  237. cProc AddPatchAppCache, <PUBLIC, NEAR>, <ds>
  238. parmW hExe
  239. parmD hkeyReg
  240. cBegin
  241. SetKernelDSNRes
  242. mov ax, hExe
  243. mov hExePatchAppCache, ax
  244. mov edx, hkeyReg
  245. mov hkeyPatchAppCache, edx
  246. if KDEBUG
  247. push cx
  248. mov cx, hkeyPatchAppCache.hi
  249. krDebugOut DEB_WARN,"AddPatchAppCache: (#ax, #cx#dx)"
  250. pop cx
  251. endif
  252. UnSetKernelDS
  253. cEnd
  254. ; FlushPatchAppCache
  255. ;
  256. ; Flushes an hExe from the PatchApp cache.
  257. ; If the cache has a reg key for the hExe, closes the key.
  258. ;
  259. ; Arguments:
  260. ; hExe
  261. ;
  262. ; Returns:
  263. ;
  264. ; Remarks:
  265. ; called by DelModule
  266. ;
  267. ; Registers Preserved:
  268. ; DI, SI, DS
  269. assumes ds,nothing
  270. assumes es,nothing
  271. ;VOID
  272. cProc FlushPatchAppCache, <PUBLIC, NEAR>, <>
  273. parmW hExe
  274. cBegin
  275. ; CheckKernelDS
  276. ReSetKernelDS
  277. mov ax, hExe
  278. krDebugOut DEB_TRACE,"FlushPatchAppCache: (hExe #ax)"
  279. cmp ax, hExePatchAppCache
  280. jne short fpac_exeunt
  281. sub eax, eax
  282. cmp eax, hkeyPatchAppCache
  283. je short fpac_after_close_key
  284. cCall RegCloseKey32, <hkeyPatchAppCache>
  285. if KDEBUG
  286. mov cx, hExe
  287. mov bx, hkeyPatchAppCache.lo
  288. mov dx, hkeyPatchAppCache.hi
  289. krDebugOut DEB_WARN,"FlushPatchAppCache: flushing (hExe #cx) (hkey #dx#bx)"
  290. endif
  291. fpac_after_close_key:
  292. mov hExePatchAppCache, ax
  293. if KDEBUG
  294. mov hkeyPatchAppCache, eax ; a little extra for debug
  295. endif
  296. fpac_exeunt:
  297. UnSetKernelDS
  298. cEnd
  299. ; PatchGetFileSize
  300. ;
  301. ; Get the size of a file, given the DOS file handle.
  302. ;
  303. ; Arguments:
  304. ; dfh - DOS file handle
  305. ;
  306. ; Returns:
  307. ; DWORD file size
  308. ;
  309. ; Remarks:
  310. ; Since these patches are only for old (<4.0) apps, only support
  311. ; DWORD file size.
  312. ;
  313. ; Registers Preserved:
  314. ; DI, SI, DS
  315. assumes ds,nothing
  316. assumes es,nothing
  317. ;DWORD
  318. cProc PatchGetFileSize, <PUBLIC, NEAR>, <ds,si,di>
  319. parmW dfh
  320. localV FileInformation,<SIZE BY_HANDLE_FILE_INFORMATION>
  321. localW HiPosition
  322. localW LoPosition
  323. localW SavePDB
  324. cBegin
  325. ; MultiThreading version of change PDB
  326. ; cCall GetCurPDB
  327. ; mov SavePDB, ax
  328. ; SetKernelDSNRes
  329. ; cCall SetCurPDB,<topPDB> ; kernel's PSP
  330. ; UnSetKernelDS
  331. ; MultiThreading version of change PDB
  332. SetKernelDSNRes ; ds is a scratch reg -> no need restore
  333. mov ax, topPDB
  334. xchg Win_PDB, ax ; Switch to Kernel's PDB,
  335. UnSetKernelDS
  336. mov SavePDB, ax ; saving current PDB
  337. mov bx, dfh
  338. smov ds, ss
  339. lea dx, FileInformation
  340. stc ; Real-mode drivers don't set CY on error
  341. mov ax, 71a6h
  342. int 21h
  343. jc short gfs_try_offsets
  344. mov dx, FileInformation.bhfi_nFileSizeLow.hi
  345. mov ax, FileInformation.bhfi_nFileSizeLow.lo
  346. jmp short gfs_exeunt
  347. gfs_try_offsets:
  348. ; Real-mode drivers don't support 71a6, so we do it the hard way.
  349. ; Move from current by 0 to get the current postion
  350. mov bx, dfh
  351. sub cx, cx
  352. mov dx, cx
  353. mov ax, 4201h
  354. int 21h
  355. jc short gfs_fail
  356. ; Save current position
  357. mov HiPosition, dx
  358. mov LoPosition, ax
  359. ; Get file size by moving from end by 0
  360. sub cx, cx
  361. mov dx, cx
  362. mov ax, 4202h
  363. int 21h
  364. jc short gfs_fail
  365. push dx
  366. push ax
  367. ; Restore current position
  368. mov cx, HiPosition
  369. mov dx, LoPosition
  370. mov ax, 4200h
  371. int 21h
  372. ; Don't check for error, since we can't recover any more anyway...
  373. pop ax
  374. pop dx
  375. jmp short gfs_exeunt
  376. gfs_fail:
  377. sub ax, ax
  378. mov dx, ax
  379. gfs_exeunt:
  380. ; MultiThreading version of change PDB
  381. push ax
  382. mov ax, SavePDB
  383. SetKernelDSNRes ; ds restored on proc exit
  384. mov Win_PDB, ax
  385. UnSetKernelDS
  386. ; cCall SetCurPDB,<SavePDB> ; preserves dx
  387. pop ax
  388. ; MultiThreading version of change PDB
  389. cEnd
  390. ; CompareFileBytes
  391. ;
  392. ; Compares a sequence of bytes with those at a given offset in a file.
  393. ;
  394. ; Arguments:
  395. ; dfh
  396. ; lpBytes
  397. ; cb
  398. ; dwFileOffset
  399. ;
  400. ; Returns:
  401. ; WORD, zero iff match
  402. ;
  403. ; Remarks:
  404. ; The caller is responsible for preserving the offset in the file.
  405. ;
  406. ; Registers Preserved:
  407. ; DI, SI, DS
  408. assumes ds,nothing
  409. assumes es,nothing
  410. ;WORD
  411. cProc CompareFileBytes, <PUBLIC, NEAR>, <si,di,ds>
  412. parmW dfh
  413. parmD lpBytes
  414. parmW cb
  415. parmD dwFileOffset
  416. cBegin
  417. ; Seek to dwFileOffset.
  418. mov bx, dfh
  419. mov cx, dwFileOffset.hi
  420. mov dx, dwFileOffset.lo
  421. mov ax, 4200h
  422. int 21h
  423. jc short cfb_fail
  424. if KDEBUG
  425. ; The high byte of cb _must_ be 0.
  426. mov cx, cb
  427. cmp ch, 0
  428. je short @F
  429. krDebugOut DEB_FERROR,"CompareFileBytes: cb (#cx) > 0ffh"
  430. @@:
  431. endif
  432. mov byte ptr [cb].1, 0 ; force cb < 100h
  433. ; Read from file.
  434. mov cx, cb
  435. smov ds, ss
  436. sub sp, cx
  437. mov dx, sp ; ds:dx = read buffer
  438. mov ah, 3fh
  439. int 21h
  440. jc short cps_fail_restore_stack
  441. ; Make sure we filled the buffer.
  442. cmp ax, cx
  443. jne short cps_fail_restore_stack
  444. ; Compare the bytes.
  445. les di, lpBytes ; es:di = signature bytes
  446. smov ds, ss
  447. mov si, sp ; ds:si = read buffer
  448. rep cmpsb
  449. jne short cps_fail_restore_stack
  450. sub ax, ax
  451. add sp, cb
  452. jmp short cfb_exit
  453. cps_fail_restore_stack:
  454. add sp, cb
  455. cfb_fail:
  456. or al, 1
  457. cfb_exit:
  458. cEnd
  459. ; ComparePatchSignature
  460. ;
  461. ; Tests a patch signature against an hExe.
  462. ;
  463. ; Arguments:
  464. ; hExe
  465. ; lpPatchSignature
  466. ;
  467. ; Returns:
  468. ; WORD, zero iff match
  469. ;
  470. ; Registers Preserved:
  471. ; DI, SI, DS
  472. assumes ds,nothing
  473. assumes es,nothing
  474. ;WORD
  475. cProc ComparePatchSignature, <PUBLIC, NEAR>, <si,di,ds>
  476. parmW hExe
  477. parmD lpPatchSignature
  478. localW SavePDB
  479. localW dfh
  480. localW cbNonZero
  481. localD dwFileOffset
  482. cBegin
  483. beg_fault_trap cps_fault
  484. mov es, hExe
  485. lds si, lpPatchSignature
  486. cld
  487. .errnz AP_SIG.sig_format
  488. lodsb
  489. ;---------------------------------------------------
  490. cmp al, AP_SIG_FORMAT_META
  491. jne short cps_maybe_hexe
  492. .errnz (AP_SIG_HEXE.ms_cb - AP_SIG_HEXE.ms_format) - 1
  493. cps_loop_meta:
  494. lodsb
  495. mov ah, 0
  496. mov cx, ax ; cx = size of sub-signature
  497. jcxz cps_meta_exeunt ; end of list. must be match.
  498. mov di, si
  499. add di, cx ; ds:di = next sub-signature
  500. cCall ComparePatchSignature,<hExe,ds,si>
  501. test ax, ax
  502. jnz cps_fail
  503. ; Got a match. Try the next one.
  504. mov si, di ; ds:si = next sub-signature
  505. jmp cps_loop_meta
  506. cps_meta_exeunt:
  507. jmp cps_exeunt
  508. ;---------------------------------------------------
  509. ; AP_SIG_FORMAT_HEXE
  510. ; AP_SIG_FORMAT_HEXE2
  511. cps_maybe_hexe:
  512. .errnz (AP_SIG_FORMAT_HEXE2-AP_SIG_FORMAT_HEXE)-1
  513. cmp al, AP_SIG_FORMAT_HEXE
  514. jb short cps_maybe_filesize
  515. cmp al, AP_SIG_FORMAT_HEXE2
  516. ja short cps_maybe_filesize
  517. ; Compute number of bytes in offset after first byte.
  518. mov dl, al
  519. sub dl, AP_SIG_FORMAT_HEXE
  520. .errnz (AP_SIG_HEXE.es_cb - AP_SIG_HEXE.es_format) - 1
  521. mov ah, 0
  522. cps_hexe_loop:
  523. lodsb
  524. mov cx, ax ; cx = size of signature block
  525. jcxz cps_hexe_match ; end of list. must be match.
  526. ; Set up bx with the offset in the hExe
  527. sub bx, bx ; bx = default offset (0)
  528. lodsb
  529. mov bl, al ; bl = low byte of offset
  530. test dl, dl ; more bytes?
  531. jz short @F
  532. lodsb
  533. mov bh, al ; bh = high byte of offset
  534. @@:
  535. mov di, bx ; es:di points to bytes in hExe
  536. rep cmpsb
  537. jne cps_fail
  538. jmp cps_hexe_loop
  539. cps_hexe_match:
  540. ; ax already 0
  541. jmp cps_exeunt
  542. ;---------------------------------------------------
  543. ; AP_SIG_FORMAT_FILESIZE2
  544. ; AP_SIG_FORMAT_FILESIZE3
  545. ; AP_SIG_FORMAT_FILESIZE4
  546. cps_maybe_filesize:
  547. .errnz (AP_SIG_FORMAT_FILESIZE3-AP_SIG_FORMAT_FILESIZE2)-1
  548. .errnz (AP_SIG_FORMAT_FILESIZE4-AP_SIG_FORMAT_FILESIZE3)-1
  549. cmp al, AP_SIG_FORMAT_FILESIZE2
  550. jb short cps_maybe_file
  551. cmp al, AP_SIG_FORMAT_FILESIZE4
  552. ja short cps_maybe_file
  553. ; Compute number of non-zero bytes in file size high word
  554. mov cl, al
  555. sub cl, AP_SIG_FORMAT_FILESIZE2
  556. push cx
  557. ; MultiThreading version of change PDB
  558. ; cCall GetCurPDB
  559. ; mov SavePDB, ax
  560. ; SetKernelDSNRes es
  561. ; cCall SetCurPDB,<topPDB> ; kernel's PSP
  562. ; UnSetKernelDS es
  563. ; MultiThreading version of change PDB
  564. push ds
  565. SetKernelDSNRes
  566. mov ax, topPDB
  567. xchg Win_PDB, ax ; Switch to Kernel's PDB,
  568. UnSetKernelDS
  569. pop ds
  570. mov SavePDB, ax ; saving current PDB
  571. ; Since these patches are only for old (<4.0) apps, only support
  572. ; DWORD file size.
  573. or ax, -1
  574. cCall FarGetCachedFileHandle,<hExe,ax,ax>
  575. cmp ax, -1
  576. je short cps_filesize_fh_cache_miss
  577. cCall PatchGetFileSize,<ax>
  578. pop cx ; cl = non-zero bytes in file size high word
  579. ; Low word of file size must match.
  580. ; [si] = low byte of signature file size
  581. cmp ax, [si]
  582. jne short cps_filesize_fail
  583. mov ch, 0
  584. sub bx, bx ; bx = default high word of file size (0)
  585. jcxz cps_filesize_compare_high
  586. ; [si] = low word of signature file size
  587. inc si
  588. inc si
  589. ; [si] = low byte of high word of signature file size (if exists)
  590. ; bx = 0
  591. ; cx = [1|2], non-zero bytes in file size high word
  592. lodsb
  593. mov bl, al
  594. dec cl
  595. jcxz cps_filesize_compare_high
  596. lodsb
  597. mov bh, al
  598. cps_filesize_compare_high:
  599. cmp bx, dx
  600. jne short cps_filesize_fail
  601. cps_filesize_match:
  602. ; File size matches.
  603. ; MultiThreading version of change PDB
  604. ; cCall SetCurPDB,<SavePDB>
  605. ; MultiThreading version of change PDB
  606. mov ax, SavePDB
  607. push ds
  608. SetKernelDSNRes
  609. mov Win_PDB, ax
  610. UnSetKernelDS
  611. pop ds
  612. sub ax, ax
  613. jmp cps_exeunt
  614. cps_filesize_fh_cache_miss:
  615. krDebugOut DEB_ERROR,"ComparePatchSignature: filesize fh cache miss"
  616. cps_filesize_fail:
  617. ; MultiThreading version of change PDB
  618. ; cCall SetCurPDB,<SavePDB>
  619. ; MultiThreading version of change PDB
  620. mov ax, SavePDB
  621. push ds
  622. SetKernelDSNRes
  623. mov Win_PDB, ax
  624. UnSetKernelDS
  625. pop ds
  626. jmp cps_fail
  627. ;---------------------------------------------------
  628. ; AP_SIG_FORMAT_FILE2
  629. ; AP_SIG_FORMAT_FILE3
  630. ; AP_SIG_FORMAT_FILE4
  631. cps_maybe_file:
  632. .errnz (AP_SIG_FORMAT_FILE3-AP_SIG_FORMAT_FILE2)-1
  633. .errnz (AP_SIG_FORMAT_FILE4-AP_SIG_FORMAT_FILE3)-1
  634. cmp al, AP_SIG_FORMAT_FILE2
  635. jb cps_bad_format
  636. cmp al, AP_SIG_FORMAT_FILE4
  637. ja cps_bad_format
  638. ; Compute number of non-zero bytes in file offset high word
  639. mov cl, al
  640. sub cl, AP_SIG_FORMAT_FILE2
  641. mov ch, 0
  642. mov cbNonZero, cx
  643. ; MultiThreading version of change PDB
  644. ; cCall GetCurPDB
  645. ; mov SavePDB, ax
  646. ; SetKernelDSNRes es
  647. ; cCall SetCurPDB,<topPDB> ; kernel's PSP
  648. ; UnSetKernelDS es
  649. ; MultiThreading version of change PDB
  650. push ds
  651. SetKernelDSNRes
  652. mov ax, topPDB
  653. xchg Win_PDB, ax ; Switch to Kernel's PDB,
  654. UnSetKernelDS
  655. pop ds
  656. mov SavePDB, ax ; saving current PDB
  657. mov es, hExe
  658. or ax, -1
  659. push es
  660. cCall FarGetCachedFileHandle,<es,ax,ax>
  661. pop es
  662. cmp ax, -1
  663. je short cps_file_fh_cache_miss
  664. mov bx, ax ; bx = dos file handle
  665. mov dfh, ax
  666. sub cx, cx
  667. mov dx, cx
  668. mov ax, 4201h
  669. int 21h
  670. jc cps_fail
  671. mov dwFileOffset.hi, dx
  672. mov dwFileOffset.lo, ax
  673. cps_file_loop:
  674. lodsb
  675. mov ah, 0
  676. mov cx, ax ; cx = size of signature block
  677. jcxz cps_file_match ; end of list. must be match.
  678. mov di, cx ; di = number of bytes to match
  679. ; Get the file offset into dx:bx
  680. ; First get the low word.
  681. lodsw
  682. mov bx, ax ; bx = low word of file offset
  683. ; Get one or both bytes of the high word.
  684. sub dx, dx ; dx = default high word of file offset (0)
  685. mov cx, cbNonZero
  686. jcxz cps_file_compare
  687. ; [si] = low byte of high word of file offset
  688. ; dx = 0
  689. ; cx = [1|2], non-zero bytes in file offset high word
  690. lodsb
  691. mov dl, al
  692. dec cl
  693. jcxz cps_file_compare
  694. lodsb
  695. mov dh, al
  696. cps_file_compare:
  697. ; ds:[si] = bytes to match in file
  698. ; di = byte count
  699. ; dx:bx = offset in file
  700. cCall CompareFileBytes,<dfh,ds,si,di,dx,bx>
  701. test ax, ax
  702. jnz short cps_file_fail
  703. add si, di ; ds:si = next signature block
  704. jmp cps_file_loop
  705. cps_file_fh_cache_miss:
  706. krDebugOut DEB_ERROR,"ComparePatchSignature: file fh cache miss"
  707. cps_file_fail:
  708. or al, 1
  709. jmp short cps_file_exit
  710. cps_file_match:
  711. sub ax, ax
  712. cps_file_exit:
  713. mov si, ax ; si = return value
  714. ; Restore file position
  715. mov bx, dfh ; bx = dos file handle
  716. mov cx, dwFileOffset.hi
  717. mov dx, dwFileOffset.lo
  718. mov ax, 4200h
  719. int 21h
  720. ; Don't check error, since we can't do anything anyway.
  721. if KDEBUG
  722. jnc short @F
  723. krDebugOut DEB_ERROR,"ComparePatchSignature: failure restoring file position"
  724. @@:
  725. endif
  726. ; MultiThreading version of change PDB
  727. ; cCall SetCurPDB,<SavePDB>
  728. ; MultiThreading version of change PDB
  729. mov ax, SavePDB
  730. push ds
  731. SetKernelDSNRes
  732. mov Win_PDB, ax
  733. UnSetKernelDS
  734. pop ds
  735. mov ax, si
  736. jmp short cps_exeunt
  737. ;---------------------------------------------------
  738. end_fault_trap
  739. cps_fault:
  740. fault_fix_stack
  741. krDebugOut DEB_ERROR,"ComparePatchSignature: trapped fault"
  742. cps_bad_format:
  743. krDebugOut DEB_ERROR,"ComparePatchSignature: invalid format"
  744. cps_fail:
  745. or al, 1 ; ensure we return "no_match"
  746. cps_exeunt:
  747. cEnd
  748. ; GetPatchAppRegKey
  749. ;
  750. ; Determines if we patch an app at load time, gets reg key if so.
  751. ;
  752. ; Arguments:
  753. ; hExe
  754. ;
  755. ; Returns:
  756. ; HKEY, non-zero iff we segment-patch info in the registry for this app.
  757. ;
  758. ; Registers Preserved:
  759. ; DI, SI, DS, ES
  760. assumes ds,nothing
  761. assumes es,nothing
  762. ;HKEY
  763. cProc GetPatchAppRegKey, <PUBLIC, FAR>, <si,di,ds,es>
  764. parmW hExe
  765. szKey_size = 200
  766. abPatchSignature_size = 100
  767. localD hkeyModule
  768. localD hkeySignature
  769. localD dwIndex
  770. localV szKey,szKey_size ; BUGBUG need a better size
  771. localV abPatchSignature,abPatchSignature_size ; BUGBUG need a better size
  772. cBegin
  773. ; We must refuse to patch system modules.
  774. ; Should be ok because of version check (in caller).
  775. if KDEBUG
  776. mov es, hExe
  777. cmp es:[ne_expver], 400h ; Hacks don't apply to 4.0 or above
  778. jb short @F
  779. ; Should never get here since the caller should have already checked.
  780. krDebugOut DEB_ERROR,"GetPatchAppRegKey: (#es) version later than 4.0"
  781. @@:
  782. endif
  783. cCall GetPatchAppCache,<hExe>
  784. ; ffff:ffff means a cache miss
  785. or cx, -1
  786. cmp cx, dx
  787. jne gpark_exeunt
  788. cmp cx, ax
  789. jne gpark_exeunt
  790. ; Not in the cache. Get it from the registry and add to the cache.
  791. ; Copy the subkey prefix to the buffer.
  792. lea di, szKey
  793. smov es, ss
  794. SetKernelDSNRes
  795. lea si, szREGSTR_PATH_APPPATCH
  796. mov cx, szKey_size
  797. @@:
  798. lodsb
  799. stosb
  800. test al, al
  801. loopnz @B
  802. if KDEBUG
  803. jz short @F
  804. krDebugOut DEB_ERROR,"GetPatchAppRegKey: len(szREGSTR_PATH_APPPATCH) > szKey_size"
  805. @@:
  806. endif
  807. dec di
  808. UnSetKernelDS
  809. ; Append the module's base name (pascal format).
  810. mov ds, hExe
  811. mov si, ds:[ne_restab]
  812. lodsb
  813. if KDEBUG
  814. mov ah, 0
  815. cmp cx, ax
  816. ja short @F
  817. krDebugOut DEB_ERROR,"GetPatchAppRegKey: len(reg path) > szKey_size"
  818. @@:
  819. endif
  820. movzx cx, al
  821. rep movsb
  822. sub al, al
  823. stosb ; NULL terminator
  824. ; Get the key for this module.
  825. mov hkeySignature, 0 ; In case we fail.
  826. mov eax, HKEY_LOCAL_MACHINE
  827. lea si, szKey
  828. lea di, hkeyModule
  829. ccall RegOpenKey32, <eax, ss, si, ss, di>
  830. or ax,dx
  831. jnz gpark_fail2
  832. or dwIndex, -1 ; == mov dwIndex,-1 (but smaller)
  833. gpark_loop:
  834. inc dwIndex
  835. lea si, szKey
  836. ccall RegEnumKey32, <hkeyModule, dwIndex, ss, si, 0, szKey_size>
  837. or ax, dx
  838. jnz short gpark_loop_done
  839. ; First, convert string to binary.
  840. ; Reuse szKey since we don't need path any more (we have hKeyModule).
  841. lea si, abPatchSignature
  842. lea di, szKey
  843. krDebugOut DEB_WARN,"GetPatchAppRegKey: checking signature (@ss:di)"
  844. cCall ConvertPatchStringToBinary,<ss,si,abPatchSignature_size,ss,di>
  845. ; Skip a badly formatted patch signature.
  846. test ax, ax
  847. if KDEBUG
  848. jnz short @F
  849. lea cx, szKey
  850. krDebugOut DEB_ERROR,"PatchAppSeg: bad patch signature in registry, @ss:cx"
  851. @@:
  852. endif
  853. jz gpark_loop
  854. cCall ComparePatchSignature,<hExe,ss,si>
  855. test ax, ax
  856. jne gpark_loop
  857. if KDEBUG
  858. mov ax, hExe
  859. krDebugOut DEB_WARN,"GetPatchAppRegKey: (#ax) sig matches (@ss:di)"
  860. endif
  861. ; We have a match. Get the corresponding key.
  862. lea si, szKey
  863. lea di, hkeySignature
  864. ccall RegOpenKey32, <hkeyModule, ss, si, ss, di>
  865. or ax,dx
  866. jz short gpark_add
  867. krDebugOut DEB_ERROR,"GetPatchAppRegKey: RegOpenKey failed, #dx#ax"
  868. jmp short gpark_fail
  869. gpark_loop_done:
  870. if KDEBUG
  871. test dx, dx
  872. jnz short @F
  873. cmp ax, ERROR_NO_MORE_ITEMS
  874. je short gpark_after_loop_done_err
  875. @@:
  876. krDebugOut DEB_ERROR,"GetPatchAppRegKey: unexpected error #dx#ax"
  877. gpark_after_loop_done_err:
  878. endif
  879. gpark_fail:
  880. ; Mark that there are no patches in the registry.
  881. mov hkeySignature, 0
  882. gpark_add:
  883. ; Close the reg key for the path to the end of the module name
  884. cCall RegCloseKey32, <hkeyModule>
  885. gpark_fail2:
  886. ; Add hkeySignature to the cache and set up return regs.
  887. cCall AddPatchAppCache,<hExe, hkeySignature>
  888. mov ax, hkeySignature.lo
  889. mov dx, hkeySignature.hi
  890. gpark_exeunt:
  891. cEnd
  892. ; ConvertPatchStringToBinary
  893. ;
  894. ; Convert a string of [0-9,A-F] with nibble-swapped bytes to binary.
  895. ;
  896. ; Arguments:
  897. ; lpBinary - output buffer
  898. ; cbBinary - size of output buffer in bytes
  899. ; lpString - input NULL-terminated string
  900. ;
  901. ; Returns:
  902. ; Boolean, TRUE iff we convert the entire string.
  903. ;
  904. ; Registers Preserved:
  905. ; DI, SI, DS, ES
  906. assumes ds, nothing
  907. assumes es, nothing
  908. ;BOOL
  909. cProc ConvertPatchStringToBinary, <PUBLIC, NEAR>,<di,si,ds>
  910. parmD lpBinary
  911. parmW cbBinary
  912. parmD lpString
  913. cBegin
  914. krDebugOut DEB_WARN,"ConvertPatchStringToBinary: enter"
  915. mov cx, cbBinary
  916. jcxz cpstb_bad
  917. les di, lpBinary
  918. lds si, lpString
  919. sub ah, ah
  920. cpstb_loop:
  921. lodsb
  922. cmp al, 0
  923. je short cpstb_maybe_good
  924. cmp al, ' '
  925. je cpstb_loop
  926. cmp al, ','
  927. je cpstb_loop
  928. cmp al, '0'
  929. jb short cpstb_bad
  930. cmp al, '9'
  931. ja short cpstb_maybe_lower
  932. ; digit
  933. sub al, '0'
  934. jmp short cpstb_have_nibble
  935. cpstb_maybe_lower:
  936. or al, 20h ; map upper-case to lower-case
  937. cmp al, 'f'
  938. ja short cpstb_bad
  939. cmp al, 'a'
  940. jb short cpstb_bad
  941. ; lower-case
  942. sub al, 'a'-10
  943. cpstb_have_nibble:
  944. cmp ah, 0
  945. jne short cpstb_store_byte
  946. mov ah, al
  947. or ah, 80h
  948. jmp cpstb_loop
  949. cpstb_store_byte:
  950. shl ah, 4
  951. or al, ah
  952. stosb
  953. sub ah, ah
  954. loop cpstb_loop
  955. cpstb_bad:
  956. krDebugOut DEB_ERROR, "ConvertPatchStringToBinary: bad char #al, or bad buffer size"
  957. sub ax, ax
  958. jmp short cpstb_end
  959. cpstb_maybe_good:
  960. cmp ah, 0 ; odd-length input string ?
  961. jne cpstb_bad
  962. cpstb_good:
  963. or al, 1
  964. cpstb_end:
  965. cEnd
  966. ; PatchAppSegWorker
  967. ;
  968. ; Do the work of patching an app segment.
  969. ;
  970. ; Arguments:
  971. ; wSeg - the segment we are about to patch
  972. ; wPartySeg - a data aliase of the segment we are about to patch
  973. ; cbOriginalSeg - the value returned by GlobalSize(wSeg)
  974. ; lpcbCurrentSeg - ptr to the current size of the segment
  975. ; lpBinaryPatch - the APPPATCH struct to apply to wSeg
  976. ;
  977. ; Returns:
  978. ; VOID
  979. ;
  980. ; Registers Preserved:
  981. ; DI, SI, DS
  982. assumes ds, nothing
  983. assumes es, nothing
  984. ;VOID
  985. cProc PatchAppSegWorker, <PUBLIC, NEAR>,<si,di,ds>
  986. parmW wSeg
  987. parmW wPartySeg
  988. parmW cbOriginalSeg
  989. parmD lpcbCurrentSeg
  990. parmD lpBinaryPatch
  991. localW wAddPartySeg
  992. cBegin
  993. lds si, lpBinaryPatch
  994. mov es, wPartySeg
  995. krDebugOut DEB_WARN,"PatchAppSegWorker: applying patch to party seg #es"
  996. mov al, [si].AP_COMMON.ap_format
  997. cmp al, AP_FORMAT_REPLACE
  998. jne short pasw_maybe_add
  999. ; Replace some code in a segment.
  1000. krDebugOut DEB_WARN,"PatchAppSegWorker: type==replace"
  1001. ; Check size
  1002. mov ch, 0
  1003. mov cl, [si].AP_REPLACE.apr_cb
  1004. mov al, (AP_REPLACE.apr_abOld - AP_REPLACE.apr_format)
  1005. add al, cl
  1006. add al, cl
  1007. cmp al, [si].AP_REPLACE.apr_cbSize
  1008. if KDEBUG
  1009. je short @F
  1010. mov ah, ch
  1011. mov dh, ch
  1012. mov dl, [si].AP_REPLACE.apr_cbSize
  1013. krDebugOut DEB_ERROR,"PatchAppSegWorker: actual size (#ax) != apa_cbSize (#dx)"
  1014. @@:
  1015. endif
  1016. jne pasw_end
  1017. mov di, [si].AP_REPLACE.apr_offset
  1018. add di, cx
  1019. cmp di, cbOriginalSeg
  1020. ja pasw_replace_offset_too_large
  1021. sub di, cx
  1022. add si, (AP_REPLACE.apr_abOld - AP_REPLACE.apr_format)
  1023. repe cmpsb ; compare old bytes to hExe bytes
  1024. jne pasw_repl_no_match
  1025. mov si, lpBinaryPatch.lo
  1026. mov ch, 0
  1027. mov cl, [si].AP_REPLACE.apr_cb
  1028. add si, (AP_REPLACE.apr_abOld - AP_REPLACE.apr_format)
  1029. add si, cx ; skip over the old bytes
  1030. sub di, cx ; rewind to the patch area start
  1031. rep movsb ; replace the bytes
  1032. jmp pasw_end
  1033. pasw_maybe_add:
  1034. cmp al, AP_FORMAT_ADD
  1035. jne pasw_bad_format
  1036. ; Add some code to the segment.
  1037. krDebugOut DEB_WARN,"PatchAppSegWorker: type==add"
  1038. ; Check size
  1039. mov ch, 0
  1040. mov cl, [si].AP_ADD.apr_cb
  1041. mov al, (AP_ADD.apa_abNew - AP_ADD.apa_format)
  1042. add al, cl
  1043. cmp al, [si].AP_ADD.apa_cbSize
  1044. if KDEBUG
  1045. je short @F
  1046. mov ah, ch
  1047. mov dh, ch
  1048. mov dl, [si].AP_ADD.apa_cbSize
  1049. krDebugOut DEB_ERROR,"PatchAppSegWorker: actual size (#ax) != apa_cbSize (#dx)"
  1050. @@:
  1051. endif
  1052. jne pasw_end
  1053. ; Make sure the add is beyond the original segment.
  1054. mov di, [si].AP_ADD.apa_offset
  1055. cmp di, cbOriginalSeg
  1056. jb short pasw_offset_too_small
  1057. ; Grow the segment if necessary.
  1058. mov ah, 0
  1059. mov al, [si].AP_ADD.apa_cb
  1060. add di, ax
  1061. ; See if the segment is already big enough.
  1062. les bx, lpcbCurrentSeg
  1063. cmp di, es:[bx]
  1064. jbe short pasw_do_add
  1065. ; Segment too small. Grow it.
  1066. cCall GlobalRealloc,<wSeg,0,di,0>
  1067. ; Make sure we got the same sel back.
  1068. mov cx, wSeg
  1069. and al, not 1
  1070. and cl, not 1
  1071. cmp ax, cx
  1072. jne short pasw_repl_realloc_failed
  1073. ; Save the new size of the segment.
  1074. les bx, lpcbCurrentSeg
  1075. mov es:[bx], di
  1076. pasw_do_add:
  1077. mov ch, 0
  1078. mov cl, [si].AP_ADD.apa_cb
  1079. ;Since wSeg may have grown, create a new party seg.
  1080. mov bx, wSeg
  1081. mov ax, 000Ah ;DPMI, Create Code Segment Alias
  1082. int 031h
  1083. mov es, ax
  1084. sub di, cx
  1085. add si, (AP_ADD.apa_abNew - AP_ADD.apa_format)
  1086. rep movsb ; add the bytes
  1087. cCall FreeSelector, <es>
  1088. if KDEBUG
  1089. jmp short pasw_end
  1090. endif
  1091. pasw_bad_format:
  1092. if KDEBUG
  1093. sub ah, ah
  1094. krDebugOut DEB_ERROR,"PatchAppSegWorker: unknown format #ax"
  1095. jmp short pasw_end
  1096. endif
  1097. pasw_repl_realloc_failed:
  1098. if KDEBUG
  1099. mov ax, wSeg
  1100. krDebugOut DEB_ERROR,"PatchAppSegWorker: realloc failed on seg #ax"
  1101. jmp short pasw_end
  1102. endif
  1103. pasw_repl_no_match:
  1104. if KDEBUG
  1105. krDebugOut DEB_WARN,"PatchAppSegWorker: replace failed in seg #es"
  1106. jmp short pasw_end
  1107. endif
  1108. pasw_offset_too_small:
  1109. if KDEBUG
  1110. mov cx, cbOriginalSeg
  1111. krDebugOut DEB_ERROR,"PatchAppSegWorker: add offset (#di) < size (#cx)"
  1112. jmp short pasw_end
  1113. endif
  1114. pasw_replace_offset_too_large:
  1115. if KDEBUG
  1116. mov cx, cbOriginalSeg
  1117. krDebugOut DEB_ERROR,"PatchAppSegWorker: replace offset (#di) > size (#cx)"
  1118. endif
  1119. pasw_end:
  1120. cEnd
  1121. ; PatchAppSeg
  1122. ;
  1123. ; Apply any patches for the given segment.
  1124. ;
  1125. ; Arguments:
  1126. ; hkeyPatchApp - reg key containing patches for this app
  1127. ; wSegNo - number of the segment in the module
  1128. ; wSeg - selector of the segment
  1129. ;
  1130. ; Returns:
  1131. ; BOOL - ax!=0 iff one or more patches applied
  1132. ;
  1133. ; Registers Preserved:
  1134. ; CX, DI, SI, DS, ES
  1135. assumes ds, nothing
  1136. assumes es, nothing
  1137. ;BOOL
  1138. cProc PatchAppSeg, <PUBLIC, FAR>,<cx,si,di,ds,es>
  1139. parmD hkeyPatchApp
  1140. parmW wSegNo
  1141. parmW wSeg
  1142. szKey_size = 5
  1143. szValString_size = 32
  1144. abValData_size = 100
  1145. abBinaryPatch_size = 100
  1146. localD hkey
  1147. localV szKey,szKey_size ; BUGBUG need a better size
  1148. localV szValString,szValString_size ; BUGBUG need a better size
  1149. localV abValData,abValData_size ; BUGBUG need a better size
  1150. localV abBinaryPatch,abBinaryPatch_size ; BUGBUG need a better size
  1151. localD cbValString
  1152. localD cbValData
  1153. localD dwType
  1154. localD dwIndex
  1155. localW cbOriginalSeg
  1156. localW cbCurrentSeg
  1157. localW wPartySeg
  1158. cBegin
  1159. if KDEBUG
  1160. mov ax, wSegNo
  1161. mov bx, wSeg
  1162. krDebugOut DEB_WARN,"PatchAppSeg: enter, (wSegNo #ax) (wSeg #bx)"
  1163. endif
  1164. push wSeg
  1165. call GlobalSize
  1166. mov cbOriginalSeg,ax
  1167. mov cbCurrentSeg,ax
  1168. ; Segment number is the subkey.
  1169. lea si, szKey
  1170. cCall Far_htoa0, <ss, si, wSegNo>
  1171. mov bx, ax
  1172. mov byte ptr ss:[bx], 0 ; NULL terminator
  1173. ; Get the key for this module/seg pair.
  1174. lea si, szKey
  1175. lea di, hKey
  1176. cCall RegOpenKey32, <hkeyPatchApp, ss, si, ss, di>
  1177. or ax,dx
  1178. jnz pas_no_patches
  1179. ; Turn off the code bit for the seg to make it writeable.
  1180. ; NB - Bail if this is a data segment.
  1181. mov bx, seg gdtdsc
  1182. mov ds, bx
  1183. assume ds:nothing
  1184. mov ds, ds:gdtdsc
  1185. mov bx, wSeg
  1186. and bl, not 7
  1187. test byte ptr ds:[bx+5], DSC_CODE_BIT
  1188. jz pas_no_patches ; bail if data seg
  1189. mov bx, wSeg
  1190. mov ax, 000Ah ;DPMI, Create Code Segment Alias
  1191. int 031h
  1192. mov wPartySeg, ax
  1193. ; Mark this code segment not discardable so we don't have to deal
  1194. ; with patching it again.
  1195. call Far_genter
  1196. mov dx, wSeg
  1197. call Far_pdref
  1198. ; ds:esi = arena record
  1199. and ds:[esi].pga_flags, not (GA_DISCARDABLE or GA_DISCCODE)
  1200. call Far_gleave
  1201. or dwIndex, -1
  1202. pas_loop:
  1203. sub ecx, ecx
  1204. inc dwIndex
  1205. push dword ptr hkey
  1206. push dword ptr dwIndex
  1207. mov cbValString, szValString_size
  1208. mov cbValData, abValData_size
  1209. push ss
  1210. lea ax, szValString
  1211. push ax
  1212. push ss
  1213. lea ax, cbValString
  1214. push ax
  1215. push ecx
  1216. push ss
  1217. lea ax, dwType
  1218. push ax
  1219. push ss
  1220. lea ax, abValData
  1221. push ax
  1222. push ss
  1223. lea ax, cbValData
  1224. push ax
  1225. cCall RegEnumValue32
  1226. or ax, dx
  1227. jnz pas_loop_done
  1228. if KDEBUG
  1229. lea bx, szValString
  1230. krDebugOut DEB_WARN,"PatchAppSeg: found patch @ss:bx"
  1231. endif
  1232. cmp dwType, REG_BINARY
  1233. jne short pas_bad_type
  1234. lea bx, abValData ; ss:bx points to patch
  1235. movzx ecx, ss:[bx].AP_COMMON.ap_cbSize
  1236. cmp cbValData, ecx
  1237. if KDEBUG
  1238. je short @F
  1239. push bx
  1240. mov eax, cbValData
  1241. mov edx, eax
  1242. ror edx, 16
  1243. mov ebx, ecx
  1244. ror ebx, 16
  1245. krDebugOut DEB_ERROR,"PatchAppSeg: actual size (#dx:#ax) != ap_cbSize (#bx:#cx)"
  1246. pop bx
  1247. @@:
  1248. endif
  1249. jne pas_loop
  1250. pas_apply_patch:
  1251. lea ax, cbCurrentSeg ; ss:ax points to curr seg size
  1252. ; Now apply the patch.
  1253. cCall PatchAppSegWorker,<wSeg,wPartySeg,cbOriginalSeg,ss,ax,ss,bx>
  1254. jmp pas_loop
  1255. pas_bad_type:
  1256. if KDEBUG
  1257. mov eax, dwType
  1258. mov edx, eax
  1259. ror edx, 16
  1260. krDebugOut DEB_WARN,"PatchAppSeg: unimplemented type #dx:#ax"
  1261. endif
  1262. jmp pas_loop
  1263. pas_no_patches:
  1264. sub ax, ax
  1265. jmp short pas_end
  1266. pas_loop_done:
  1267. if KDEBUG
  1268. test dx, dx
  1269. jnz short @F
  1270. cmp ax, ERROR_NO_MORE_ITEMS
  1271. je short pas_cleanup
  1272. @@:
  1273. krDebugOut DEB_WARN,"PatchAppSeg: unexpected error #dx#ax"
  1274. endif
  1275. pas_cleanup:
  1276. cCall FreeSelector, <wPartySeg>
  1277. cCall RegCloseKey32, <hkey>
  1278. or al, 1 ; ax!=0 marks patch found in reg
  1279. pas_end:
  1280. cEnd
  1281. sEnd NRESCODE
  1282. end